block的基本语法和应用
block的基本语法和应用
云飞扬v5 发表于2年前
block的基本语法和应用
  • 发表于 2年前
  • 阅读 39
  • 收藏 2
  • 点赞 2
  • 评论 0

华为云·免费上云实践>>>   

摘要: 介绍了block的基本语法和用法

代码片段block基本语法

block就是一段语句组成的代码段,可以认为整个block里面就是一句代码,可以有参数和返回值。可以看看下面几种常见的情况。

不带参数无返回值

这里是打印系统时间的一个例子

   //无参数,无返回值的block
    void (^logTime)(void)=^{
        NSLog(@"time is ==%@",[NSDate date]);
    };
    
    //调用block
    logTime();
    
    /*
     print time is ==2016-05-21 02:13:08 +0000

     
     */

不带参数有返回值

获取当前时间的例子

  //不带参数,有返回值
    NSDate* (^getNowDate)(void)=^{
        return [NSDate date];
    };
    
    NSDate *nowDate=getNowDate();
    NSLog(@"nowDate==%@",nowDate);
//    print nowDate==2016-05-21 02:43:24 +0000

 

带参数无返回值

打印传入的参数

   //有参数,无返回值的block
    void (^logInput)(NSString *input)=^(NSString *input){
        NSLog(@"input==%@",input);
        
    };
    //调用logInput
    logInput(@"abc");
  
    // print input==abc

 

 

带参数有返回值

单个参数

对传入参数乘以7

    //有参数,有返回值
    int (^multiplierBy7)(int)=^(int multiplier){
        return multiplier*7;
    };
    int result= multiplierBy7(3);
    NSLog(@"result==%i",result);
    // print result==21

多个参数

传入4个参数的情况,计算立方体的体积

    //有多个参数,有返回值的block
    double (^calculateCubicVolume)(double ,double ,double ,NSString *)=^(double length,double width,double height,NSString *cubicName){
        double volume=length*width*height;
        NSLog(@"cubic name==%@",cubicName);
        return volume;
    };
    //调用block
    double volume1=calculateCubicVolume(1,2,3,@"cubic demo 1");
    NSLog(@"volume==%f",volume1);
    /*
    print
        cubic name==cubic demo 1
        volume==6.000000
     */

 

作为函数的参数

 

定义函数

void testFunction(int i1,void(^actionBlock)(int)){
    if (actionBlock) {
        actionBlock(i1);
        NSLog(@"in function i1==%i",i1);
    }
}

 

调用函数

   testFunction(1024, ^(int i2) {
     
        NSLog(@"use function i2 ==%i",i2);
    });
    /*
    print use function i2 ==1024
    in function i1==1024
     */

作为方法的参数

__block BOOL found = NO;
NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil];
NSString *string = @"gamma";
 
[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
    if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {
        *stop = YES;
        found = YES;
    }
}];
 
// At this point, found == YES

 

 

作为属性

直接声明作为属性的block

  
//声明block类型的属性

#import "HBTestBlock.h"

@interface HBTestBlock ()
@property(nonatomic, copy) UIView *(^viewGetter)(NSString *imageName); //注意其返回类型为UIView *

@end

//在另一个类中调用

 HBTestBlock *objPropertyBlockObj = [[HBTestBlock alloc] init];
    objPropertyBlockObj.viewGetter = ^(NSString *imageName){
//        return [[UIView alloc] init]; //特别注意此处,若对象不匹配,则会报错,设置为nil也会报错。
        return [self currentView];
    };


    objPropertyBlockObj.viewGetter(@"hello"); //实际执行block

 

通过typedef 简化定义的过程


#import "ViewController.h"


typedef int(^compareBlock)(int a, int b);


@interface ViewController ()
//声明属性的block
//使用简化方式的定义
@property (nonatomic,copy) compareBlock compare1;

//使用基本方式进行定义
@property (nonatomic,copy) int (^compare2)(int a,int b);

//void类型block 属性的定义
@property (nonatomic,copy) void (^networkFailure)(NSError *error);

//对象类型的block属性的定义
@property (nonatomic,copy) UIView *(^getAView)(NSString *imageName);



@implementation ViewController

-(void)viewDidLoad{
 //赋值属性的block
    self.compare1=^(int a,int b){
        NSLog(@"compare1 a==%d,b==%d,result==%@",a,b,a>b?@"a>b":@"a<=b");
        return a>b;
        
    };

    self.compare2=^(int a,int b){
        NSLog(@"compare2 a==%d,b==%d,result==%@",a,b,a>b?@"a>b":@"a<=b");
        return a>b;
        
    };

 //执行属性的block,这里没有接收返回值
    
    if (self.compare1) {
         self.compare1(5,6);
    }
    
    if (self.compare2) {
         self.compare2(5,6);
    }




}


@end


/*
print 打印结果
  compare1 a==5,b==6,result==a<=b
  compare2 a==5,b==6,result==a<=b

*/

 

 

避免循环引用

 

block的应用

封装网络请求

对某些经常变化的部分代码做封装

 

因为block的调用和实现是分开的,所以可以处理一些变化的代码。比如数组中做筛选的条件就可以是一个bool返回类型的block,或者对数组进行排序的场景中,返回2个元素的顺序的代码用block实现,这样就有了很大的灵活性。

下面就举一个数字排序的例子

/**
 *  排序的方法
 *
 *  @param numberArray 输入的数组
 *  @param comparator  比较2个数字大小的block
 *
 *  @return 返回排序后的数组
 */
-(NSArray *)sortNumberWithNumberArray:(NSArray *)numberArray
                      comparatorBlock:(BOOL(^)(NSNumber *,NSNumber *))comparator{
    /**
     *  存放排序前的数组
     */
    NSMutableArray *beforeSort=numberArray.mutableCopy;
    /**
     *  存放排序后的数组
     */
    NSMutableArray *afterSort=[NSMutableArray array];
    //每次循环确定第j+1个最大的数字
    for (int j=0; j<numberArray.count; j++) {
        
        //假设第一个元素就是最大的结果
        NSNumber *maxNumber=[beforeSort firstObject];
        
        
        for (int i=0; i<beforeSort.count; i++) {
            NSNumber *numberIndex=beforeSort[i];
           //用比较大小的block进行比较,其实这里并不知道block的内容,只是确定了block的返回值和参数。后续调用的时候,可以进行多种条件的实现
            BOOL largerThanPreviousMax= comparator(numberIndex,maxNumber);
            //如果遇到一个比之前最大数字还大的数字,那就把当前最大的数字放在maxNumber里面
            if (largerThanPreviousMax==YES) {
                maxNumber=numberIndex.copy;
                
            }
            
        }
        
        //将取到的第j+1个数移出排序前数组,放入排序后数组
        [beforeSort removeObject:maxNumber];
        [afterSort addObject:maxNumber];
        
    }

    return afterSort.copy;

}

 

调用的时候,定义了2个不同的场景,按照数字的整数大小排列,以及按照绝对值大小进行排序

 //排序前的数组
    NSArray *array=@[@1,@(-2),@3,@(-9),@4,@8];
    //根据数值的大小进行排序
    BOOL (^comparator)(NSNumber*,NSNumber*)=^(NSNumber *num1,NSNumber *num2){
        BOOL result=[num1 integerValue]>[num2 integerValue];
        return result;
    };
    NSArray *resultArray=[self sortNumberWithNumberArray:array comparatorBlock:comparator];
    
    
    
    NSLog(@"resultArray%@",resultArray);
    /*
    print   resultArray(
                        8,
                        4,
                        3,
                        1,
                        "-2",
                        "-9"
                        )
     
     */

    //根据绝对值的大小进行排序
    BOOL (^absoluteSortComparator)(NSNumber *,NSNumber *)=^(NSNumber *num1,NSNumber *num2){
    
        BOOL result=fabs([num1 doubleValue])>fabs([num2 doubleValue]);
        return result;
    
    };
    NSArray *absoluteSortArray=[self sortNumberWithNumberArray:array comparatorBlock:absoluteSortComparator];
    NSLog(@"absoluteSortArray%@",absoluteSortArray);
    
/*
    print  absoluteSortArray(
                             "-9",
                             8,
                             4,
                             3,
                             "-2",
                             1
                             )
 */

 

block传值的应用场景介绍

有2个控制器,A控制器显示一个问题,你最喜欢的数字是哪个?点了选择以后就跳转到B控制器,在B控制器有一个列表,可以供用户选择。需求就是在B中选择了以后,A中做出相应的修改。

 

接下来就上代码了

首先是第一个页面

.h 

#import <UIKit/UIKit.h>

@interface FavouriteNumberViewController : UIViewController

@end

 

.m

//
//  FavouriteNumberViewController.m
//  BlockPassValue
//

//

#import "FavouriteNumberViewController.h"

#import "ChoosingFavouriteNumberViewController.h"

@interface FavouriteNumberViewController ()

@property (nonatomic,weak) UILabel *favouriteNumberLabel;



@end

@implementation FavouriteNumberViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UILabel *favouriteNumberLabel=[[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 100)];
    favouriteNumberLabel.font=[UIFont systemFontOfSize:13.0];
    
    favouriteNumberLabel.backgroundColor=[UIColor greenColor];
    
    [self.view addSubview:favouriteNumberLabel];
    self.favouriteNumberLabel=favouriteNumberLabel;
    
    UIButton *pickNumberButton=[[UIButton alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
    
    [pickNumberButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [pickNumberButton setTitle:@"点击选择数字" forState:UIControlStateNormal];
    [pickNumberButton addTarget:self action:@selector(pickupNumber) forControlEvents:UIControlEventTouchUpInside];
    pickNumberButton.backgroundColor=[UIColor orangeColor];
    
    [self.view addSubview:pickNumberButton];
    
    
    
    // Do any additional setup after loading the view.
}


-(void)pickupNumber{

    ChoosingFavouriteNumberViewController *choosingNumberVC=[[ChoosingFavouriteNumberViewController alloc]init];
    __weak typeof (self) weakSelf=self;
    choosingNumberVC.chooseNumberBlock=^(NSString *number){
        weakSelf.favouriteNumberLabel.text=[NSString stringWithFormat:@"最喜欢的数字是%@",number];
       
        
    };
    
    [self.navigationController pushViewController:choosingNumberVC animated:YES];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

 

.h

#import <UIKit/UIKit.h>

typedef  void (^ChooseNumberBlock) (NSString *number) ;

@interface ChoosingFavouriteNumberViewController : UIViewController

@property (nonatomic,copy) ChooseNumberBlock chooseNumberBlock;

@end

 

 

.m

//
//  ChoosingFavouriteNumberViewController.m
//  BlockPassValue
//

//

#import "ChoosingFavouriteNumberViewController.h"

@interface ChoosingFavouriteNumberViewController ()
<UITableViewDataSource,UITableViewDelegate>

@property (nonatomic,weak) UITableView *tableView;

@property (nonatomic,strong) NSArray *numberArray;

@end

@implementation ChoosingFavouriteNumberViewController
#pragma mark - vc life cycle
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title=@"请选择你喜欢的数字";
    UITableView *tableView=[[UITableView alloc]init];
    tableView.delegate=self;
    tableView.dataSource=self;
    [self.view addSubview:tableView];
    
    tableView.frame=self.view.bounds;
    self.tableView=tableView;
    
    self.view.backgroundColor=[UIColor whiteColor];
    

    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - data getter

-(NSArray *)numberArray{

    if (!_numberArray) {
       
        NSMutableArray *numberArray=[NSMutableArray array];
        for (int i=0; i<10; i++) {
            [numberArray addObject:[NSString stringWithFormat:@"%i",i]];
        }
        _numberArray=numberArray.copy;
    }
    return _numberArray;

}
#pragma mark -table view datasource

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.numberArray.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier=@"cellIdentifier";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if(!cell){
    
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.textLabel.text=self.numberArray[indexPath.row];
    
    return cell;

}

#pragma mark - table view delegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

//调用了之前定义的block内容
    if (self.chooseNumberBlock) {
        NSString *selectedNumber=self.numberArray[indexPath.row];
        self.chooseNumberBlock(selectedNumber);
    }
    [self.navigationController popViewControllerAnimated:YES];
    

}


@end

 

 

 

 

 

 

 

 

block中的变量的对应管理

局部变量

全局变量

__block修饰的变量

 

 

 

 

参考资料

重要经验五:block作为属性的注意事项

http://blog.csdn.net/lvmaker/article/details/25468485

 

 

共有 人打赏支持
粉丝 11
博文 74
码字总数 67465
×
云飞扬v5
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: