紧凑禁用自引用块的arc-retain-cycles警告

Cha*_*ves 15 objective-c clang objective-c-blocks automatic-ref-counting

我正在编写一个涉及事件处理的API,我希望能够为处理程序使用块.回调通常需要访问或修改self.在ARC模式中,Clang警告说引用self的块可能会创建一个保留周期,这似乎是一个有用的警告,我想继续保持.

但是,对于我的这部分API,回调的生命周期和包含对象在外部进行维护.我知道当对象应该被释放时我可以打破循环.

我可以在每个文件的基础上关闭保留周期警告#pragma clang diagnostic ignored "-Warc-retain-cycles",但是会禁用整个文件的警告.我可以围绕一个块#pragma clang diagnostic pushpop周围的警告,但是这使得该块难看.

我还可以通过引用指向self的__weak变量而不是直接引用self来获取警告消失,但这使得块使用起来不那么令人愉快.

我提出的最好的解决方案是这个宏在块周围执行诊断禁用:

#define OBSERVE(OBJ, OBSERVEE, PATH, CODE) \
[(OBJ) observeObject:(OBSERVEE) forKeyPath:(PATH) withBlock:^(id obj, NSDictionary *change) { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-retain-cycles\"") \
do { CODE; } while(0); \
_Pragma("clang diagnostic pop") \
}];
Run Code Online (Sandbox Code Playgroud)

这是有效的,但它对于API用户来说不是很容易被发现,它不允许嵌套的观察者,并且它与XCode的编辑器交互不良.有没有更好的方法来禁用或避免警告?

Sas*_*ats 7

首先,有一种简单的方法可以使用#pragma以下方法禁用某些代码行的警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "<#A warning to ignore#>"
<#Code that issues a warning#>
#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)

但我不会在这种特殊情况下使用它,因为它不能解决问题,它只是将它隐藏在开发人员之外.我宁愿选择马克提出的解决方案.要创建弱引用,可以在块外部执行以下操作之一:

__weak typeof(self) weakSelf = self; // iOS ? 5
__unsafe_unretained typeof(self) unsafeUnretainedSelf = self; // 5 > iOS ? 4
__block typeof(self) blockSelf = self; // ARC disabled
Run Code Online (Sandbox Code Playgroud)