Xcode 9.3升级后Block隐式保留self警告的成因与处理疑问
关于Xcode 9.3中Block隐式保留self警告的问题解析
嘿,我来帮你把这个问题掰扯清楚!
为什么升级Xcode后突然冒出来警告?
Xcode 9.3搭配的LLVM 9.0编译器调整了默认的警告策略——把「Block内隐式保留self」的检测默认开启了。你之前用旧版本Xcode编译时,这个警告可能默认是关闭状态,所以没触发,升级后就显形了。
两种已验证的解决方法
- 方法一:显式通过
self->score访问成员变量
当你在Block里直接写score时,编译器会偷偷捕获self来访问这个成员变量,改成self->score相当于明明白白告诉编译器“我就是要通过self访问”,警告自然就消失了,这也是你亲测有效的方法。 - 方法二:修改编译器警告开关
你提到的另一个新回答里的操作,就是在Xcode的Build Settings中,找到Apple LLVM 9.0 - Warnings - Objective C and ARC分类下的Implicit retain of 'self' in block选项,把它从Yes改成No,就能直接关闭这个警告。不过我得提醒你:不建议随便关,这个警告是编译器帮你排查内存泄漏风险的重要提示。
彻底搞懂Block隐式保留self的核心问题
这里的关键是理解Block的捕获机制:
- 当你在Block内部直接访问对象的成员变量(比如
score)时,编译器不会直接捕获这个成员变量,而是自动捕获self——也就是说,Block会悄悄对self持有一个强引用。 - 这种隐式强引用最容易踩的坑就是循环引用:如果
self本身也持有这个Block(比如把Block赋值给self的某个属性),就会形成self → Block → self的强引用环,导致两者都无法被系统回收,最终造成内存泄漏。 - 编译器开启这个警告,本质是在提醒你:“喂,你这里偷偷抓了self,小心内存泄漏哦!”
那更稳妥的处理方式是什么?除了显式写self->score,更推荐用弱引用来打破循环引用风险,代码示例如下:
__weak typeof(self) weakSelf = self; [self.someAsyncTask executeBlock:^{ // 用strongSelf避免Block执行过程中self被释放 __strong typeof(weakSelf) strongSelf = weakSelf; if (strongSelf) { strongSelf.score = 100; // 或者 strongSelf->score = 100; } }];
这样既消除了警告,又从根源上避免了循环引用的隐患。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

