关于ios:了解在其中访问self的块的保留计数。

Understanding retain count with the blocks accessing self inside it.

我对块的弱引用有基本的了解。 我面临的问题是,

每当我在块内访问self时,self的保留计数增加2,而当我在默认块(例如UIViewAnimation)中访问self时,self的保留计数增加1。

只是想明白为什么它会增加2。
enter image description here

提前致谢!


根据Clang源代码生成Objective-C块的代码。

  • CGBlocks.cpp
  • CGDecl.cpp
  • CGObjC.cpp

Objective-C块文字由EmitBlockLiteral函数生成。

1
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {

LLVM文档深入解释了什么是块文字。无论如何,这个函数生成一个块描述符和指定块的复制辅助函数。复制助手功能用于捕获自动变量和self

1
buildBlockDescriptor -> buildCopyHelper -> GenerateCopyHelperFunction

GenerateCopyHelperFunction函数中,Clang为每个将被块捕获的Objective-C对象自动变量发出objc_storeStrong

1
2
3
for (const auto &CI : blockDecl->captures()) {
    ...
    EmitARCStoreStrongCall(...

因此,此行将计算self(1 - > 2)的保留计数。

之后,EmitBlockLiteral函数也会为每个将被块捕获的Objective-C对象自动变量发出objc_retain

1
2
3
4
// Next, captured variables.
for (const auto &CI : blockDecl->captures()) {
    ...
    EmitExprAsInit -> EmitScalarInit -> EmitARCRetain

因此,该行也会计算self的保留计数(2 - > 3)。

我不知道确切的原因。但显然,有一些理由在通过块复制助手函数捕获对象之前保留Objective-C对象。


在块中使用self通常会创建一个循环,这可能是它增加2的原因。要解决这个问题,你应该尝试使用弱自我。检查这个问题

在这个区块中强烈捕获自我可能会导致保留周期

使用这样的东西
__unsafe_unretained typeof(self)weakSelf = self;