美文网首页
iOS block的用法举例

iOS block的用法举例

作者: 绚雨蓝了个枫 | 来源:发表于2017-12-20 17:35 被阅读12次

    一、Block的几种写法

    1、有返回值、有参数列表

    先介绍一下Block语法的书写,首先来看一个完整的Block:

        int (^ExistReturnValueWithExistParameterBlock)(int num);
        
    //   “^”这个符号表示这是一个Block;
    //    返回值:int表示返回值类型
    //    变量名:ExistReturnValueWithExistParameterBlock
    //    参数列表:(int num)这个括号中是Block的参数
        
        ExistReturnValueWithExistParameterBlock = ^ int(int num){    
             NSLog(@"有参数列表,参数为:%d,有返回值,返回值为:%d",num,300+num);
             return 300+num;
        };
        
        ExistReturnValueWithExistParameterBlock(500);
    
        打印结果:有参数列表,参数为:500,有返回值,返回值为:800
    

    也可以省略不写Block的返回值,例如以下写法:

        int (^ExistReturnValueWithExistParameterBlock)(int num);
    
        ExistReturnValueWithExistParameterBlock = ^(int num){
            return 300+num;
        };
    
        ExistReturnValueWithExistParameterBlock(500);
    

    2、没有返回值,没有参数列表

    完整写法①:

        void (^NoReturnValueWithNoParameterBlock)(void) = ^void(void) {
            NSLog(@"没有返回值,没有参数列表");
        };
        
        NoReturnValueWithNoParameterBlock();
    
        打印结果:没有返回值,没有参数列表
    

    完整写法②:

        void (^NoReturnValueWithNoParameterBlock)(void);
    
        NoReturnValueWithNoParameterBlock = ^void(void) {
            NSLog(@"没有返回值,没有参数列表");
        };
    
        NoReturnValueWithNoParameterBlock();
    

    简略写法①:

        void (^NoReturnValueWithNoParameterBlock)() = ^ {
            NSLog(@"没有返回值,没有参数列表");
        };
    
        NoReturnValueWithNoParameterBlock();
    

    简略写法②:

        void (^NoReturnValueWithNoParameterBlock)();
    
        NoReturnValueWithNoParameterBlock = ^ {
            NSLog(@"没有返回值,没有参数列表");
        };
        
        NoReturnValueWithNoParameterBlock();
    

    3、没有返回值,有参数列表

    完整写法①:

       void(^ExistParameterBlock)(int num) = ^(int num){
            NSLog(@"没有返回值,有参数列表,参数为:%d",num);
        };
    
        ExistParameterBlock(100);
    
        打印结果:没有返回值,有参数列表,参数为:100
    

    完整写法②:

        void(^ExistParameterBlock)(int num);
        
        ExistParameterBlock = ^(int num){
             NSLog(@"没有返回值,有参数列表,参数为:%d",num);
        };
    
        ExistParameterBlock(100);
    

    4、有返回值、没有参数列表

    完整写法:

        int(^ExistReturnValueBlock)();
        
        ExistReturnValueBlock = ^ int{
            return 200;
        };
        
        NSLog(@"没有参数列表,有返回值,返回值为:%d",ExistReturnValueBlock());
    
        打印结果:没有参数列表,有返回值,返回值为:200
    

    二、Block改变外部变量的值

    1、非集合对象

       int value = 11;
       void (^changeValueBlock)() = ^{
          value = 33;
       };
    

    这段代码编译出错,编译器提示的大概就是不能在Block中改变变量的值。因为在Block中截获了变量的瞬间值以后就不能再改变变量的值,如果想要在Block中改变变量的值,那么我们只需要在变量声明的时候加上__block修饰符。

    如下:

        __block int value = 11;
        NSLog(@"value改变之前:%d", value);
        void (^changeValueBlock)() = ^{
            value = 33;
        };
        changeValueBlock();
        NSLog(@"value改变之后:%d", value);
    
        打印结果:value改变之前:11
        打印结果:value改变之后:33
    

    2、集合对象

    和非集合对象不一样。对于集合对象,因为我们只是对截获的变量进行了操作,而没有进行赋值,所以对于截获变量,可以进行操作而不可以进行赋值。

        NSMutableArray *array = [[NSMutableArray alloc]init];
        NSLog(@"array改变之前:%@", array);
        void (^changeArrayBlock)() = ^{
            [array addObject:@"block"];
        };
        changeArrayBlock();
        NSLog(@"array改变之后:%@", array);
    
        打印结果:array改变之前:( )
        打印结果:array改变之后:( block, )
    

    三、Block当作函数参数

    具体代码如下:

    //
    //  SecondViewController.m
    //
    
    #import "SecondViewController.h"
    
    typedef void(^ParameterBlock)(NSString *str);
    
    @interface SecondViewController ()
    
    @end
    
    @implementation SecondViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //Block当作函数参数
        [self testBlockMethod:^(NSString *str) {
            NSLog(@"%@",str);
        }];
    }
    
    - (void)testBlockMethod:(ParameterBlock)block {
        block(@"测试block为函数参数");
    }
    
    @end
    

    四、Block逆向传值

    在APP页面跳转过程,如果A 页面--> B页面是正向的话,那么我们把B页面的值传给A就叫做 反向传值、逆向传值(或者叫做回调)。
    首先建立两个控制器HomeViewController(A)和TestViewController(B),HomeViewController(A) 跳转到TestViewController(B) 。HomeViewController(A)作为捕获方,TestViewController(B)作为传值方。

    1、传值方---TestViewController(B)

    TestViewController.h文件

    //
    //  TestViewController.h
    //  
    //  谁传值,谁就写block
    
    #import <UIKit/UIKit.h>
    
    typedef void(^TransmitBlock)(NSString *title);
    
    @interface TestViewController : UIViewController
    
    @property (nonatomic, copy) TransmitBlock block;
    
    @end
    

    TestViewController.m文件

    //
    //  TestViewController.m
    //
    
    #import "TestViewController.h"
    
    @interface TestViewController ()
    
    @property (nonatomic, strong) UIButton *testBtn;
    
    @end
    
    @implementation TestViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        _testBtn = [[UIButton alloc]initWithFrame:CGRectMake(200, 200, 55, 55)];
        [self.view addSubview:_testBtn];
        _testBtn.backgroundColor = [UIColor redColor];
        [_testBtn setTitle:@"点击" forState:UIControlStateNormal];
        [_testBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [_testBtn addTarget:self action:@selector(clickedBtn) forControlEvents:UIControlEventTouchUpInside];
    }
    
    - (void)clickedBtn {
        self.block(@"block测试");
    }
    
    @end
    

    2、捕获方---HomeViewController(A)

    HomeViewController.m文件

    //
    //  HomeViewController.m
    //
    
    #import "HomeViewController.h"
    #import "TestViewController.h"
    
    @interface HomeViewController ()
    
    @property (nonatomic, strong) UILabel *titleLab;
    @property (nonatomic, strong) UIButton *clickBtn;
    
    @end
    
    @implementation HomeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.titleLab = [[UILabel alloc]initWithFrame:CGRectMake(200, 100, 100, 30)];
        [self.view addSubview:self.titleLab];
        self.titleLab.backgroundColor = [UIColor yellowColor];
        self.titleLab.textColor = [UIColor blueColor];
        self.titleLab.font = [UIFont systemFontOfSize:20.0];
    
        self.clickBtn = [[UIButton alloc]initWithFrame:CGRectMake(200, 200, 55, 55)];
        [self.view addSubview:self.clickBtn];
        self.clickBtn.backgroundColor = [UIColor redColor];
        [self.clickBtn setTitle:@"跳转" forState:UIControlStateNormal];
        [self.clickBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [self.clickBtn addTarget:self action:@selector(jumpToTestVC) forControlEvents:UIControlEventTouchUpInside];
    }
    
    - (void)jumpToTestVC {
        
        TestViewController *testVC = [[TestViewController alloc]init];
        
        __weak typeof(self) weakself = self;
        
        testVC.block = ^(NSString *title){
            
            __strong typeof(weakself) strongSelf = weakself;
            
            strongSelf.titleLab.text = title;
        };
        
        // weakSelf是为了block不持有self,避免循环引用,而再声明一个strongSelf是因为一旦进入block执行,就不允许self在这个执行过程中释放。block执行完后这个strongSelf会自动释放,没有循环引用问题。
        [self.navigationController pushViewController:testVC animated:YES];
    }
    @end
    

    相关文章

      网友评论

          本文标题:iOS block的用法举例

          本文链接:https://www.haomeiwen.com/subject/tbwgwxtx.html