强引用self.view接收含self的Block参数,是否会产生循环引用及强引用Block?
关于Block循环引用的问题解答
咱们一步步拆解这个问题,先给你明确结论,再慢慢说细节:
首先判断self.view是否强引用该Block:
这完全取决于touchActionWithCompeletion:方法内部对Block参数的处理逻辑。如果这个方法把传入的Block作为**实例变量(比如用strong属性存储)**保存起来了(比如self.view内部有个@property (strong, nonatomic) void(^completionBlock)(NSString *);,然后在方法里把Block赋值给这个属性),那self.view就会强引用这个Block;如果方法只是临时使用Block(比如立刻执行一次就完事,不存到任何实例变量里),那self.view不会持有这个Block的强引用。再来说是否会产生循环引用:
循环引用的核心是「互相强引用形成闭环」,咱们梳理下可能的引用链:- self通过strong属性,必然强引用self.view;
- Block内部直接访问了self,所以Block会自动生成对self的强引用;
- 如果上面说的self.view也强引用了Block,那引用链就变成了:
self → self.view → Block → self,完美形成闭环,这时候就会产生循环引用,导致三者都无法被系统释放; - 如果self.view没有强引用Block(只是临时用一下),那引用链只有
self → self.view,Block执行完就会被释放,不会形成闭环,也就没有循环引用问题。
给你个通用的避坑建议:不管self.view会不会存Block,都可以提前weak化self来规避潜在风险,代码示例如下:
__weak typeof(self) weakSelf = self; [self.view touchActionWithCompeletion:^(NSString *text){ __strong typeof(weakSelf) strongSelf = weakSelf; if (strongSelf) { strongSelf.label.text = text; } }];
这样既避免了循环引用,也能防止Block执行过程中self被提前释放导致的野指针问题。
内容的提问来源于stack exchange,提问作者XM Zhang
相关产品推荐
相关产品推荐

