概念
什么是 Blocks?
- Blocks 是对 C 语言的扩展,也就是带有局部变量的匿名函数;
- 它的好处是是使得
Objective-C
可以像 JavaScript 一样进行函数式编程;
Blocks 的一些特点:
- 块可接受参数,也可返回值。
- 块可以分配在栈或堆上,也可以是全局的,分配在栈上的块可拷贝到堆里。
- 和标准的 Objective-C 对象一样,具备引用计数了。
定义块
定义一个块对象基础的语法是:
|
|
很显然这是一个匿名函数,就像 JavaScript 一样,也可以像下面一样直接执行:
|
|
但是通常我们定义一个 Blocks 时,通常是需要一个名字的:
|
|
这样定义的块可以通过像 C 中的语法一样调用:someBlock()
常见问题
块的强大之处是:
在声明它的范围里。所有变量都可以为其所捕获。这也就是说,那个范围里的全部变量,在块里依然可用。
比如,下面这段代码所定义的块,就使用了块以外的变量:
1 2 3 4 5 6
int additional = 5; int (^addBlock)(int a, int b) = ^(int a, int b){ return a + b + addItional; }; int add = addBlock(2, 5); // < add = 12
我们也可以为常用的块创建 typedef
:
|
|
但是 blocks 一般是不可以主动修改局部变量的,需要修改的话则需要添加 __block
关键字:
|
|
循环引用:
因为块也是一个对象,如果你在块的代码引用了
self
这个变量,则会导致循环引用。比如:1 2 3 4 5 6 7 8 9 10 11 12 13 14
@interface ViewController () @property (nonatomic, copy) NSString *name; @property (nonatomic, strong) CompletionHandler handler; @end @implementation ViewController - (void)blocks { self.handler = ^{ NSLog(@"%@", self.name); }; } @end
这样的循环引用的代码,是会被 xcode 检测出来的。
我们可以声明一个
__weak
的局部变量解决这个问题:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@interface ViewController () @property (nonatomic, copy) NSString *name; @property (nonatomic, strong) CompletionHandler handler; @end @implementation ViewController - (void)blocks { __weak __typeof(self)weakSelf = self; self.handler = ^{ __strong __typeof(weakSelf)strongSelf = weakSelf; NSLog(@"%@", strongSelf.name); }; } @end
在 Objective-C
中,NSArray
提供了一个传入块依次执行的函数,其名为 enumerateObjectsUsingBlock
。比如下面是一个遍历数组的示例代码:
|
|