今天遇到这样子一个场景,嵌套Block下的外层strongSelf是否会产生循环引用
先看Demo 代码:
- (void)testRetainCycle {
__weak typeof(self) weakSelf = self;
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)self)));
self.doWork = ^{
__strong typeof(self) strongSelf = weakSelf;
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)strongSelf)));
weakSelf.doStudent = ^{
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)strongSelf)));
};
weakSelf.doStudent();
};
self.doWork();
}
先说结论: 这里会产生循环引用的
并且是self和doStudent互相持有导致的循环引用。
从memory graph 上看也确实是这样子:
那么为什么呢?我们知道在ARC中:
__weak:
- __weak用于声明弱引用,不会增加对象的引用计数。这是为了避免循环引用问题,常用于解决持有对象之间的强引用循环。
- 如果一个对象只有__weak引用,当没有强引用指向它时,对象会被释放,这可以防止循环引用。
但是当我们在Block里面去用StrongSelf去持有一个weak引用的时候,会导致weak的引用计数+1,这么做一般是用来避免block内的对象被提前释放。
那我们再回到这个代码里面, 在这里
__strong typeof(self) strongSelf = weakSelf;
weakSelf的引用计数+1, 可以理解为这里的doWork 持有了 strongSelf/ weakSelf。
那么在weakSelf被+1的情况, 那么doStudent也被doWork持有了。
那么引用关系就出现了, doStudent 里面又持有了 strongSelf。
本来正常的情况是在doWork执行完成以后释放strongSelf的, 但是因为strongSelf被doStudent 持有了无法释放。
weakSelf持有了doStudent, 因为weakSelf没有释放,所以doStudent 也无法释放了。
这里形成了循环引用。
下面是解决办法:
- (void)testRetainCycle {
__weak typeof(self) weakSelf = self;
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)self)));
self.doWork = ^{
__strong typeof(self) strongSelf = weakSelf;
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)strongSelf)));
weakSelf.doStudent = ^{
__strong typeof(self) strongSelf2 = weakSelf;
NSLog(@"B objc doStudent strong-----retainCount : %lu", CFGetRetainCount(((__bridge CFTypeRef)strongSelf2)));
};
weakSelf.doStudent();
};
self.doWork();
}
这里在内层用另一个临时变量去引用weak,可以解决循环引用,从这里也能看出来循环引用的持有原因
PS:这里用memory graph调试 内存问题真的很好用
网友评论