弱/强"跳舞"在手动内存管理中

时间:2014-09-04 13:25:16

标签: ios objective-c objective-c-blocks

使用手动内存管理(又名非ARC)设想以下场景:

我有一个VC将块传递给类方法。在执行块之前,VC会从UINavigationController中弹出。 __block MyVC *weakSelf = self形式的弱引用传递给块,然后转换为MyVC *strongSelf = weakSelf(又称弱/强舞)。任何干预者都不会保留该区块。

在这种情况下,我在代码中看到的是:

  1. 当弹出VC时会调用VC的dealloc。
  2. 最终会调用该块。
  3. 应用程序崩溃,因为我正在访问垃圾邮件(strongSelf指向它)。
  4. 我的问题是:我不想让我的VC保持活着,直到块最终执行,但是一旦块被执行,我想确认strongSelf是有效的。

    我已经检查了这个(non-trivial example by Apple)这个没有用,因为它的设计考虑了ARC。那么我如何才能与MMM有相同的行为?理想情况下,我希望得到__weak所做的事情:如果retainCount达到零,我希望它的引用指向nil而不是垃圾。


    从Apple阅读之后:

      

    在某些情况下,如果不是,则可以使用__unsafe_unretained   __weak兼容。然而,这对于非平凡的周期来说变得不切实际,因为它可能很难或不可能进行验证   __unsafe_unretained指针仍然有效且仍然指向   对于相同的对象。

    由于我无法访问__weak我想要做什么甚至可能?

2 个答案:

答案 0 :(得分:1)

我在iOS 4.x天回到了这个问题。如果没有弱指针可以帮助你,那就不容易了!

如果你保证稍后在主线程上执行块(即从weakSelf分配strongSelf的地方)那么你基本上需要一个地方存储一个" isDead"标志,在VC被解除分配时设置。然后在使用weakSelf / strongSelf执行任何操作之前检查此标志。一个解决方案就是:

  1. 你需要一个班级,他们唯一的工作就是存储这个" isDead"成员变量中的标志。类似NSMutableBoolean的东西。我不会写出一个,它很简单,它只需要一个BOOL属性。
  2. 在VC的-[NSObject init]方法中,您可以创建此标志对象的实例,该实例最初应设置为false
  3. 然后,您将此对象传递给您排队等待以后执行的任何块,以便块自动保留/释放(即不经过弱/强舞)。在块中,在使用weakSelf执行任何操作之前,检查标志是否仍为NO
  4. 关键当然是在VC的YES方法中将标志设置为-[NSObject dealloc],然后释放它。如果任何块仍在等待执行,它们将自己保留标记对象,并且当它们稍后执行时,它们将查询该标志,发现VC现在已经死亡。
  5. 这听起来很麻烦(而且有点)但是这个想法是" isDead" flag生活之外 VC的范围,因此不依赖于它的生命周期。至于线程安全性,只要你只在VC的init / dealloc方法中设置/查询标志,并且当执行该块时(在主线程上,而不是在后台线程上),它将是线程安全的。

答案 1 :(得分:0)

  

我不希望我的VC在块最终执行之前保持活着

但为什么这很重要?一个VC的内存不应该那么多,如果该块在VC上执行任何UI操作,那也没关系,因为VC无论如何都不会显示。

基本上,如果VC不保留块,则块不应捕获对VC的弱引用。使用非归零弱引用意味着您可以保证对象保持活动状态,这不是这里的情况。我建议你不要做这件弱事。