当一个 block 捕获了 self 指针时
有可能会出现循环引用的问题。
出现时,self 强引用 block,block 又强引用了 self,那么就需要使出「强弱共舞」来解除 block 对 self 的强引用了。
self.name = @"Hello";
__weak typeof(self) weakSelf = self;
self.block = ^(){
__strong __typeof(weakSelf)strongWeak = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", strongWeak.name);
});
};
self.block();
__strong 只在 block 内部生效,block 执行完了以后强引用关系不再出现
__block 关键字的语义
将一个变量包装成一个struct A,后续对这个变量的访问都会转变成对strut A中一个属性的访问。
// 定义一个 block 获取局部变量 myVariable
- (void)testBlock {
__block NSInteger myVariable = 100;
void (^myBlock)(void) = ^{
NSLog(@"myVariable = %ld", myVariable);
oooo = 99;
NSLog(@"修改后, myVariable = %ld", myVariable);
};
myBlock();
}
struct __Block_byref_myVariable_0 {
void *__isa;
__Block_byref_myVariable_0 *__forwarding;
int __flags;
int __size;
NSInteger myVariable;
};
对于 myVariable 的访问就变成了对结构体中
__Block_byref_myVariable_0.myVariable 成员变量的访问
于是,本来 block 对于外部的基本变量是无法修改的,但是现在既然都装到了一个结构体·里,那么值传递就变成了指针传递,修改就易如反掌了。
将.m文件编译成 cpp 文件:
clang -rewrite-objc BlockDemo.m
,可以看到这个Block 持有的属性
如果是某个对象的属性值,不需要用 __block
, 因为这个属性值也是一个标量罢了(内存地址)。标量本身并没有修改。只是标量指向的内存地址修改了,对 block 没有影响,block 不需要持有标量指向的值。