iOS Block 实现原理
iOS Block __block 说明符
最近又翻了一遍《Objective-C 高级编程》, 每读一遍感觉都不一样, 理解的东西印象更深了. 在此做一下笔记. 推荐 iOS 开发者细读几遍, 很受益.
这篇简单说下 Block 语法及使用:
Block 概要
什么是 Block: 带有自动变量 (局部变量) 的匿名函数
匿名函数: 没有名称的函数.
自动变量: 局部变量, 函数参数.
其他语言中的 Block 的名称
程序语言 | Block 的名称 |
---|---|
C+ Block | Block |
Smalltalk | Block |
Ruby | Block |
Python | Lambda |
C++ | Lambda |
JS | Anonymous function |
Block 语法
^ 返回值类型 参数列表 表达式
例:
- ^ NSString * (NSString *str) {
- return [str stringByAppendingString:@"======"];
- };
返回值类型 参数列表可以省略;
^ 表达式
例:
- ^{
- NSLog(@"我是 block");
- };
Block 类型变量
block 和 C 语言函数相比, 除了没有 ^ 和函数名称, 其他都相同.
声明 Block 类型变量并赋值:
- NSString *(^block)(NSString *) = ^ NSString * (NSString *str) {
- return [str stringByAppendingString:@"======"];
- };
- block(@"haha");//block 调用
Block 变量赋值:
NSString *(^block1)(NSString *) = block;
也可以使用 typedef 来给 Block 变量起别名:
typedef NSString * (^MyBlock)(NSString *);
使用 MyBlock 类型的属性:
@property (nonatomic, copy) MyBlock block;
函数传递 block 类型参数:
- - (void)function:(NSString *(^)(NSString *name))block {
- NSString *str = NSStringFromSelector(_cmd);
- NSLog(@"%@",block(str));
- }
block 作为函数返回值
- - (NSString *(^)(NSString *))function:(NSString *)firstName {
- return ^NSString *(NSString *lastName) {
- return [firstName stringByAppendingString:lastName];
- };
- }
- NSString *(^block2)(NSString *) = [self function:@"xiao"];
- NSLog(@"%@",block2(@"_ming"));
打印: xiao_ming
Block 截获自动变量值
通过 Block 语法和 Block 类型变量, 我们理解了带有自动变量值的 匿名函数 中的 匿名函数, 而带有自动变量值究竟是什么呢? 带有自动变量值在 Block 中表现为 截获自动变量值, 实现如下:
- - (void)viewDidLoad {
- [super viewDidLoad];
- int dmy = 256;
- int val = 10;
- const char *fmt = "val = %d\n";
- void (^blk)(void) = ^{
- printf(fmt,val);
- };
- val = 2;
- fmt = "These value were changed. val = %d\n";
- blk();
- }
打印: val = 10 而不是 These value were changed. val = 2
说明
在上述代码中, Block 语法的表达式使用的是它之前声明的自动变量 fmt 和 val.Block 中, Block 表达式截获所使用的自动变量的值, 即保存该自动变量的瞬间值. 因为 Block 表达式保存了自动变量的值, 所以在执行 Block 语法后, 即使改写 Block 中使用的自动变量的值也不会影响 Block 执行时自动变量的值.
__block 说明符
在不加__block 修饰符时, Block 截获的是自动变量值的瞬间值, 保存后就不能改写该值.
- int val = 1;
- void (^blk)(void) = ^{
- val = 2;
- };
报错: Variable is not assignable (missing __block type specifier)变量不能被赋值, 缺少__block
要想在 Block 内部改变变量的值, 需要在变量前加上 __block
该变量称为__block 变量. 后边会说明,__block 到底做了哪些事情.
- __block int val = 1;
- void (^blk)(void) = ^{
- val = 2;
- };
截获 OC 对象
- NSMutableArray *array = [NSMutableArray array];
- void (^blk)(void) = ^{
- [array addObject:@"haha"];
- //array = [NSMutableArray array]; 编译报错, 缺少__block 修饰符
- };
赋值给截获的 array 对象会编译报错, 但是使用截获的值却不会有任何问题.
本章要点:
什么是 Block
Block 语法
Block 基本使用
Block 截获自动变量值
__block 修饰符
来源: http://www.jianshu.com/p/2921fdb0ff59