理解在块内访问self时的保留计数。
Objective-C中的block是一个闭包,可以访问其外部作用域的变量和自动变量。但是在使用block中访问self时,会出现retain count(引用计数)的问题。
根据Clang源代码生成Objective-C block的代码,Objective-C的block字面量是通过EmitBlockLiteral函数生成的。在生成block字面量时,会生成一个block描述符和一个复制帮助函数,复制帮助函数用于捕获自动变量和self。
在生成复制帮助函数时,Clang会对每个会被block捕获的Objective-C对象自动变量进行objc_storeStrong操作,这会增加self的引用计数。接着,在EmitBlockLiteral函数中,还会对每个会被block捕获的Objective-C对象自动变量进行objc_retain操作,同样会增加self的引用计数。
至于为什么在捕获对象之前需要增加其引用计数,目前还不清楚。但显然有某种原因导致在复制帮助函数中捕获对象之前需要先增加其引用计数。
解决这个问题的方法是,在复制帮助函数中对捕获的对象进行引用计数的减法操作,即调用objc_release函数。这样可以保证在block释放时引用计数的正确性。
总结起来,Objective-C中的block访问self时会导致retain count的增加,可以通过在复制帮助函数中对捕获的对象进行引用计数的减法操作来解决这个问题。
使用块内的self通常会创建一个循环,这可能是增加2的原因。为了解决这个问题,你应该尝试使用弱引用。请查看这个问题
capturing self strongly in this block is likely to lead to a retain cycle
使用类似下面的代码:
__unsafe_unretained typeof(self) weakSelf = self;
在块内使用self不会创建一个循环。它只会在块内创建一个对self的引用。只有当你创建一个循环时,即如果你保留了从self到块的引用时,才会创建一个循环。这不是这里发生的情况。