美文网首页
Block的详细使用(五)

Block的详细使用(五)

作者: 凉白开0072 | 来源:发表于2017-12-11 11:14 被阅读11次

    Block 的初步理解

    1. 例如定义一个block:void(^myblock)(int);=>与int a;比较
    2. block的类型:void(^)(int);=>等价于int
    3. block的变量名:myblock=>等价于a
    4. 注意:
      1. 定义block时若有输入参数(本例为int),参数名可有(int x)可无(int)但必须有参数的类型,但实现是必须有参数的类型和变量名.
      2. 实现block时,也可以将block返回类型写在实现中(通常不写),写在仅仅挨着^后面,不需要(),这样有利于让实现者知道该block返回什么值,(其实这样写更加规范,苹果官方有使用:当带有返回值的block作为一个方法的参数时,当调用这个方法时,系统的提示代码在block实现中会加上返回类型,具体看典例)
     //实现中写返回参数类型
        NSString *(^myblockx)(int) = ^NSString *(int a){
            return @"";
        };
        //实现中不写返回参数类型
        NSString *(^myblockx2)(int) = ^(int a){
            return @"";
        };
    

    定义一个block

    1. 无返回值有参数

       //定义一个block变量,然后给这个变量赋值:myblock
      //此时void(^)(int)为类型名,myblock1为变量名
      //int a ; a = 3;
      void(^myblock1)(int);
      myblock1 = ^(int a){
      };
      //定义一个block变量并赋值//int a = 3;
      void(^myblock2)(int) = ^(int a){
      };
      
    2. 无返回值无参数

        //1.先定义,在赋值
      void(^myblock0)();
      myblock0 = ^{
      };
      //2.定义时赋值(略)
      
    3. 有返回值无参数

       //1.先定义,在赋值(略)
      //2.定义时赋值
      int(^myblock4)()=^{
          return 3;
      };
      
    4. 有返回值有参数且参数(注意参数中可以有变量名也可以没有变量名,变量名与实现时参数的变量名无关联)

       //1.先定义,在赋值
      int(^myblock7)(int c ,int d);
      myblock7 = ^(int a, int b){
          return a + b;
      };
      //2.定义时赋值
      int(^myblock6)(int ,int) = ^(int a, int b){
          return a + b;
      };
      
      
    5. 参数为block

      //重要:block的传入参数为block类,理解!!!!
      //1.定义时赋值(参数block无变量名)
      //同理当传入参数为block时,可以有变量名,也可以无变量名
      //传入的block类型为void(^)():无返回值无参数型
      int(^blockx)(void(^)())= ^(void(^x)()){
          return 2;
      };
      //2.先定义,在赋值(参数block有变量名:mmm,参数block中的参数名q也是可有可无)
      //传入的block类型为int(^)(int):有返回值有参数型
      int(^blocky)(int(^mmm)(int q));
      blocky = ^(int(^x)(int a)){
          return 2;
      };
      

    使用typedef定义block类

    1. 面向对象思想:将block定义成一个自定义类,然后使用这个类创建变量赋值block,使用typedef
    //定义一个sumblock类(参数中的变量名可有可无)
        typedef int(^sumblock)(int c ,int d);
        sumblock block = ^(int a,int b){
            return a + b;
        };
        //实质:
        // sumblock block;等价于 int(^block)(int,int);
        //用block替换掉sumblock;
        
        //举例:定义一个blockz,传入参数为sumblock类,然后赋值
        //sumblock只是类型,变量名可有可无,也可以传入sumblock vvv
        int(^blockz)(sumblock);
        blockz = ^(sumblock block2){
            return 2;
        };
    

    Block的常见使用

    1. block成为属性
      1. 举例:

        @property (nonatomic, strong) void(^operation)();
        @property (nonatomic, strong) NSString *operation;
        
      2. 作用: 把block保存到对象中,恰当时机的时候才去调用

      3. 注意:这里容易引发循环引用,引起原因前面讲过,如何解决(weakself),不再赘述.

    2. block成为方法参数:传入一个block参数
      1. 举例:

          - (void)eat:(void(^)(int))block;
        - (void)eat:(nsstring *)block;
        
      2. 作用: 把block当做方法的参数使用,外界不调用,都是方法内部去调用,Block实现交给外界决定.(注意理解)

    3. 成为返回参数:该方法返回一个block
      1. 举例:

        - (void(^)(int))run;
        -(nsstring *)run;
        
      2. 作用:把block当做方法的返回值,目的就是为了代替方法,block交给内部实现,外界不需要知道Block怎么实现,只管调用

    举例使用:

    //Person.h
    
    #import <Foundation/Foundation.h>
    // name:类型的别名
    typedef void(^BlockName)();
    
    @interface Person : NSObject
    
    //block作为属性
    // block:既可以使用copy,也可以使用strong,但是建议用copy
    // block类型:void(^)()
    @property (nonatomic, strong) void(^operation)();
    
    //block 作为参数
    // 参数类型:block类型
    - (void)eat:(void(^)())block;
    - (void)eat2:(BlockName)block;
    //传入参数block带返回值类型
    - (void)eat3:(NSString *(^)(int))block;
    
    //block作为返回值
    - (void)run:(int)metre;
    - (void(^)(int))run;
    @end
    
    #import "Person.h"
    
    @implementation Person
    - (void)eat:(void (^)())block
    {
        block();
    }
    -(void)eat3:(NSString *(^)(int))block{
        block(3);
    }
    - (void)run:(int)metre
    {
        NSLog(@"%d",metre);
    }
    - (void (^)(int))run
    {
        return ^(int meter){
            NSLog(@"跑了%d米",meter);
        };
    }
    -(void)eat2:(BlockName)block{
        block();
    }
    @end
    
    //viewcontroller
    
    #import "ViewController.h"
    #import "Person.h"
    @interface ViewController ()
    @property (nonatomic, strong) Person *p;
    @end
    
    @implementation ViewController
    
    //block作为方法返回值(代码在内部,调用在外部)
    - (void)block3
    {
        Person *p = [[Person alloc] init];
        [p run:2];
        //注意理解;p.run等价于[p run];
        //注意这两种调用结果一样,第二种是第一种的实现过程
        p.run(2);//调用方法:非常牛逼!!!!
        void(^run)(int) = p.run;
        run(2);
        //虽然p.run返回的是一个void(^)(int)类型的block,但这样写也对void(^run)(),没写参数就是参数都为0,run()就是传入参数为0
        void(^run2)() = p.run;
        run2();
    }
    
    //block作为方法参数(外部传代码,调用在内部)
    - (void)block2
    {
        Person *p = [[Person alloc] init];
        void(^block)() = ^{
            NSLog(@"吃东西");
        };
        [p eat:block];
        [p eat2:block];
        // 传入block给参数的Block赋值
        [p eat:^{
            NSLog(@"吃东西");
        }];
        //该block实现可以没有block返回类型:NSString *,但有更规范
        [p eat3:^NSString *(int a) {
            return [NSString stringWithFormat:@"该block实现中有返回值类型NSString,传入参数为:%zd",a];
        }];
    }
    
    //block作为属性(保存一段代码到对象中)
    - (void)block1
    {
        Person *p = [[Person alloc] init];
        void(^block)() = ^() {
            NSLog(@"执行对象中block");
        };
        p.operation = block;
        p.operation = ^(){
            NSLog(@"执行对象中block");
        };
        _p = p;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        //执行对象中保存的block
        _p.operation();
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:Block的详细使用(五)

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