Block基本语法结构
- 定义语法:
返回值类型 (^block名称)(参数列表) = ^返回值类型(参数列表) { 代码块 };
- 简化语法:当返回值类型可以从代码块推断出来时,返回值类型部分可以省略。即
(^block名称)(参数列表) = ^(参数列表) { 代码块 };
简单Block定义示例
// 定义一个简单的Block,接收两个int类型参数,返回它们的和
int (^sumBlock)(int, int) = ^(int a, int b) {
return a + b;
};
// 调用Block
int result = sumBlock(3, 5);
NSLog(@"结果: %d", result);
ARC环境下Block捕获对象时的内存管理机制
- 强引用捕获:在ARC环境下,Block默认会对捕获的对象进行强引用。当Block被创建时,会保留(retain)捕获的对象,这确保了在Block执行期间,被捕获的对象不会被释放。例如:
NSObject *obj = [[NSObject alloc] init];
void (^block)(void) = ^{
NSLog(@"%@", obj);
};
// 此时block对obj有强引用
- __weak修饰符:为了避免循环引用(例如,对象A持有一个Block,而Block又捕获了对象A),可以使用
__weak
修饰符来捕获对象。__weak
修饰的变量不会增加对象的引用计数,从而打破循环引用。例如:
__weak typeof(self) weakSelf = self;
self.block = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
// 使用strongSelf访问对象属性或方法,这样在block执行期间,对象不会被释放
}
};
- __block修饰符(对于对象):在ARC中,
__block
修饰符在捕获对象时,对象的内存管理行为与非__block
捕获时有所不同。如果用__block
修饰对象,Block对该对象的引用是弱引用(但在Block内部使用时,实际操作的是强引用,会自动增加引用计数)。不过,为了避免循环引用,__weak
通常是更好的选择,__block
更多用于处理基本数据类型和在Block内需要修改外部变量的情况。例如:
__block NSObject *blockObj = [[NSObject alloc] init];
void (^block2)(void) = ^{
NSLog(@"%@", blockObj);
};
// 这里block2对blockObj的引用相对特殊,实际执行时会涉及更复杂的内存管理操作,但整体是为了在满足需求的同时尽量合理管理内存