Block OC的特有数据类型

相信有开发经验的人都对block不陌生,它与c语言的block相似但是也有不同之处。

有兴趣的同学可以通过运行时机制看看oc的c语言代码,通过CLong有助于对底层构建的了解。如果你对函数的指针,指针的指针不了解还是回去复习一下吧...

复习过后有几点问题需要强调,面试的时候也可能会提到


  • 首先是block的基本定义:
    1. BlockOC中的一种数据类型,在iOS开发中被广泛使用
    2. ^Block的特有标记
    3. Block的实现代码包含在{}之间
    4. 大多情况下,以内联inline函数的方式被定义和使用
    5. BlockC语言的函数指针有些相似,但使用起来更加灵活

  • 示例

         void(^demoBlock)() =^ {

            NSLog(@"demoBlock");

         };

         int(^sumBlock)(int, int) =^(int x, int y) {

            return x +y;

          };


  • 格式说明:
    ( 返回类型 )(^ 块名称 )( 参数类型 ) = ^ ( 参数列表 ) { 代码实现 };
    如果没有参数,等号后面参数列表的 () 可以省略

    注意:
    (1) 在定义 Block 时,会在 Block 建立当前局部变量内容的副本 ( 拷贝 )
    (2) 后续再对该变量的数值进行修改,不会影响 Block 中的数值
    (3) 如果需要在 block 中保持局部变量的数值变化,需要使用 __block 关键字
    (4)使用__block关键字后,同样可以在Block中修改该变量的数值


  • Block可以被当做参数直接传递

    NSArray *array= @[@"张三",@"李四",@"王五",@"赵六"];

    [array enumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL*stop) {

       NSLog(@"%d 项内容是%@",(int)idx, obj);

       if ([@"王五"isEqualToString:obj]) {

            *stop = YES;

       }

    }];//遍历并NSLog()array中的内容,当obj"王五"停止遍历

  • 在被当做参数传递时, Block 同样可以使用 在定义之前声明 局部变量

    intstopIndex = 1;

    NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];

    [arrayenumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL *stop) {

        NSLog(@"%d 项内容是%@", (int)idx, obj);

        if ([@"王五" isEqualToString:obj] || idx == stopIndex) {

            *stop = YES;

        }

    }];

    注意 默认情况下, Block 外部的变量,在 Block 中是只读的!

    BOOL flag = NO;

    [arrayenumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL *stop) {

        if([@"王五" isEqualToString:obj] || idx == stopIndex) {

            *stop = YES;

            flag = YES;      // 编译错误!!!

            }

    }];

  • 如果要修改 Block 之外的局部变量需要使用 __block 关键字

    __block BOOL flag = NO;

    [array enumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL *stop) {

        if([@"王五" isEqualToString:obj] || idx == stopIndex) {

            *stop = YES;

            flag = YES;      // 现在可以修改了!!!

            }

    }];

    提示: 无需使用 __block 关键字,在块代码中可以 修改成员变量的数值 ( 比较少用 )
  • 对象传递进 Block 的方式

    NSString *stopName =@"王五";

    NSArray *array= @[@"张三",@"李四",@"王五",@"赵六"];

    [array enumerateObjectsUsingBlock:^(idobj, NSUIntegeridx,BOOL *stop) {

       NSLog(@"%d 项内容是%@",(int)idx, obj);

       if ([stopName isEqualToString:obj] || idx == stopIndex) {

            *stop = YES;

       }

    }];为保证Block中的代码正常运行在将stopName的指针传递给Block时,Block会自动对stopName的指针强引用

  • typedef 定义一个 Block 的类型 便于在后续直接使用

    typedef double(^MyBlock)(double, double);

    MyBlockarea = ^(double x, double y) {

        return x * y;

    };

    MyBlock sum = ^(double a, double b) {

        return a + b;

    };

    NSLog(@"%.2f", area(10.0, 20.0));

    NSLog(@"%.2f", sum(10.0, 20.0));

    说明:
    typedef 是关键字用于定义类型, MyBlock 是定义的 Block 类型
    area sum 分别是 MyBlock 类型的两个 Block 变量
  • 官方的数组遍历方法声明如下

    -(void)enumerateObjectsUsingBlock:(void(^)(id obj, NSUIntegeridx, BOOL*stop))block;

  • 既然 Block 一种数据类型 那么可以将 Block 当做比较特殊的对象

    int(^sum)(int, int) =^(int x, int y) {

       return [self sum:xy:y];

    };

    [self.myBlocks addObject:sum];

  • 循环引用-倘若你这样写代码:

    @property(nonatomic, strong) NSMutableArray *myBlocks;

     

    int(^sum)(int, int) = ^(int x, int y) {

        return [self sum:xy:y];

    };

    [self.myBlocksaddObject:sum];

     

    - (void)dealloc

    {

       NSLog(@"DemoObj被释放");

    }

    结果就是不会被释放  因为 self -> (NSMutableArray*)myBlocks -> sum -> self   死循环强指针,释放不了了
  • 解除循环引用
    局部变量默认都是强引用的 ,离开其所在的作用域之后就会被释放
    使用 __weak 关键字,可以将局部变量声明为弱引用

    __weak DemoObj *weakSelf =self;

    //在 Block 中引用 weakSelf ,则 Block 不会再对 self 做强引用

    int(^sum)(int, int) = ^(int x, int y) {

        return [weakSelf  sum:xy:y];

    };


    感谢传智播客提供的文档




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值