【问题标题】:Why not circle retain when dismiss view controller (non-arc)关闭视图控制器时为什么不圈保留(非弧)
【发布时间】:2015-01-23 04:23:56
【问题描述】:

我在非arc中有这段代码,我认为它有问题-circle retain(self(UIViewController)拥有complete-block的所有权,complete-block拥有self的所有权 )。但是当我调试时,它在 dealloc 中运行(意味着我认为没有循环保留计数)

[self dismissViewControllerAnimated:YES completion:^{
    [self goToChatViewController:buddyEntity];
}];

谁能帮我解释一下,为什么这段代码中没有圈保留?

【问题讨论】:

  • 在块中使用 self 有时会创建一个保留循环。 99% 的情况下它不会创建保留周期,并且非常安全。关键是知道什么时候出现问题……有很多可用的文档。 Stack Overflow 不是解释这一点的地方。在没有看到更多代码的情况下,我无法告诉您是否有保留周期。
  • 我认为上面的代码足以解决这个问题。我认为在我看来,self 持有完成块,完成块持有自己。但我不知道“我脑子里有什么问题”,为什么它不圈存。为什么你说“99% 的时间它不会创建保留周期”。我认为它是 100% 圈保留,但它不正确
  • 是什么让你认为上面的代码会创建一个保留循环?
  • 因为我认为“self hold completion-block,completion-block hold self”
  • 因为你没有使用 ARC,所以没有任何东西可以保留任何东西。

标签: ios objective-c


【解决方案1】:

你没有在这个区块持有参考。所以这个块在完成后被释放。 当块释放它释放它持有的对象。 所以一切正常。你可以勇敢地在这些区块中使用self

例如,如果您将块用作属性或将其添加到容器中,则会出现保留循环。

【讨论】:

  • 在 SDK 下面的代码中,我认为 UIViewController 必须将完成块保存为属性,以便在关闭完成后调用它。但它不是保留圈。如果他们不存储完成块,它如何在关闭完成时调用块?
  • @huync,UIViewController会复制块,调用后会释放。
  • 谢谢,你的回答让我明白了。接受
【解决方案2】:

一个块秘密地是一个ObjectiveC对象。当您在后台创建块时,objectiveC 创建了一个块类的实例(尽管很奇怪,它在堆栈而不是堆上创建它,除非您复制块)。块内使用的对象成为块对象的实例变量。

因为块对象在堆上,而不是在堆栈上,当你到达方法结束时,你所在的块对象超出了范围,一切都很好。但是,如果您的类在块上调用 copy 并保留引用,则该块将被复制到堆中。现在你的类引用了块,块引用了你的类,你有一个保留循环。

【讨论】:

  • 每个块都保留它使用的对象。复制块与否无关紧要。
  • 堆上的块不会增加其实例变量的保留计数。因为他们在堆上,所以他们不需要!当您对它们调用copy 时,就会发生这种情况。此时它们变成了一种稍微不同类型的对象(如果您在已复制的块对象上调用class,您会在调试器中注意到这一点)并移动到堆中。快速扫描后,这看起来像是对块 albertodebortoli.github.io/blog/2013/04/21/… 的合理解释
  • 你确定吗?您可以在块处创建指针。然后释放该块中使用的所有对象。然后从指针调用这个块。看我们没有创建块的副本,我们使用了位于堆中的块。但一切正常,因为阻止保留对象。
  • 令人震惊的是,我刚刚编写了您建议的代码,您猜怎么着?它崩溃了twistedape.me.uk/blog/images/blockCrash.png如果你想复制它,别忘了把它变成僵尸。
  • 您有EXC_BREAKPOINT 异常。这不是EXC_BAD_ACCESS。你的项目有问题。我的输出:2014-11-25 14:50:18.443 GGTest[2732:303] <NSView: 0x100129cd0>, retainCount = 1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 2016-04-23
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多