首页 > 其他 > 详细

Block中修改局部变量的值为什么必须声明为__block类型

时间:2020-04-12 11:41:08      阅读:77      评论:0      收藏:0      [点我收藏+]

更新记录

时间 版本修改
2020年4月12日 初稿

前言

最近在重新且仔细地阅读《Objective-C 高级编程 iOS与OS X多线程和内存管理》,在阅读到 2.2 Blocks模式 这章时,看到Block中截获自动变量,对其进行重新赋值,会报“缺失__block修饰符”的编译错误。这引起了我的一些思考,在此叙述一下我的思考。

思考

举书上的一个例子

block中使用该对象
id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{
  id obj = [[NSObject alloc] init];  
  [array addObject:obj];
};
  • 上述代码是没有任何问题的
block中对对象进行重新赋值
id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{
    array = [[NSMutableArray alloc] init];
};
  • 编译报错:Variable is not assignable (missing__block type specifier)
  • 网上很多参考资料上都说,给该变量加上__block修饰符就可以解决问题了。但是都没有谈到这个问题的深入之处
底层思考
  • 参考《Objective-C 高级编程 iOS与OS X多线程和内存管理》后续章节对Blocks的实现,我们可以知道,Blocks生成的结构体会捕获所用到的变量。
  • 内存指示图
    技术分享图片
  • 对于局部变量,Blocks默认捕获的是这个局部变量的值(即MemoryObj), 可以通过对MemroyObj这个地址上的内容进行修改(本质是运用了C语言的*运算符)
  • 而添加了__block说明符,则Blocks捕获的是这个局部变量的内存地址,即Memroy值(C语言中使用&操作取得一个变量的地址),这样Blocks在内部就可以通过对Memory上的数据对修改(*memroy = xxx),且可以影响到Blocks外部。
    技术分享图片
  • 没有用__block修饰的局部变量,在Blocks内部捕获了,即使修改了也没有任何意义(外部不受影响),所以编译器当初就设计了这个编译报错,避免产生不可预知的bug。

Block中修改局部变量的值为什么必须声明为__block类型

原文:https://www.cnblogs.com/HelloGreen/p/12684033.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!