在 ARC 中 child object 如何告诉 parent object 我完成了,请释放我(以避免内存泄漏)

In ARC how does a child object tells parent object I am done, please release me (to avoid memory leaks)

我的 parent object 创建了一个 child object 来执行一些异步操作。它涉及一些用户交互,这是我没有使用 NSOperation 的原因之一。只有 child object 知道它什么时候完成了它的任务,那么它如何告诉它的 parent object 我完成了,请释放我以避免内存泄漏?

目前,我想出了这个,parent object有一个回调方法叫releaseChild,就是child = nil;当 child object 完成它的任务时,它调用 parent 的 releaseChild 只是为了将自己设置为 nil。实际上,我将调用包装在 dispatch_after 中,但想法是相同的,child object 调用其 parent 将其自身设置为 nil。

我想知道有没有更好的方法?

-----更新-----

我知道 "normal" 编写 child 的方法是创建一个 UIViewController object,将其推送到 UINavigationController。完成后用户可以将其弹出,ARC 将释放它。这样,我就不必担心内存泄漏(通常)。但我认为在完成时发布 child object 的问题只有它知道何时完成具有边界应用程序而不是编写 UIViewController object.

几个可能的解决方案

1) 使用 protocol-delegation 方法让 child 告诉 parent 它完成了(我假设这就是你正在做的)

2) 您可以将变量传递给 child 并在其执行完成后由 child 设置,并且 parent 可以定期检查其值并清除 child(不是一个大粉丝,而是一种轮询方法),可以通过创建后台任务来完成,也可以添加到低优先级队列中。

3) 使用 NSNotificationCenter 向 parent 发送通知并告诉他工作已完成。您可以添加用户信息以在彼此之间识别 children。

4) 如果你不需要在工作完成后做任何具体的事情,只需使用 dispatch_async 并且不要持有参考,它会完成它的任务并最终消失

我需要更多详细信息才能为您提供有关任何特定方法的建议。如果可能的话,粘贴您的代码:)

如果子对象执行异步操作,很可能它有一个回调块,在操作完成时调用它,无论是成功还是失败。很可能父对象已经创建了子对象,存储了一个引用,告诉子对象开始异步操作,并给它回调块。所以那个回调将是设置一些对 nil 的引用的完美地方。

问题中:

Only the child object knows when it has finished its task, then how does it tell its parent object that I am done, please release me to avoid memory leaks?

并在稍后的评论中:

the problem is the child object can't set itself to nil.

看来您需要的是 child object 来控制其自身的生命周期。这很容易做到; object 只要有一个对它的引用存储在一个变量中就保持活动状态,该变量属性为断言对存储在其中的引用的强烈所有权 - 并且该属性是变量声明的默认值。该变量可以是全局的、局部的、实例的,没关系...所以要控制自己的命运,object 只需要保持对自身的引用。

以下代码是从 Manual object lifetime with ARC 复制而来的(我几年前写的一个回答,我可以从自己那里抄袭 ;-)),展示了一种方法:

@implementation MasterOfMyOwnDestiny
{
   MasterOfMyOwnDestiny *alsoMe;
}

- (void) lifeIsGood
{
    alsoMe = self;
}

- (void) woeIsMe
{
    alsoMe = nil;
}

...

@end

在您的情况下,您可以在 child 初始化期间设置 alsoMe,因此 child 开始控制其自身的生命周期。当 child 决定它已完成其工作时,它只需调用 [self woeIsMe] 作为其 final 操作。

注意:您当然可以删除方法并直接在 child 中设置实例变量,这样任何其他 object 都很难杀死 child。

如果 parent 出于任何原因需要对 child 的引用,而不是为了保持 child 存活,那么它可以将该引用存储在属性变量中断言存储在其中的引用的所有权较弱,例如类似于:

__weak MasterOfMyOwnDestiny *myChild = [MasterOfMyOwnDestiny new];

这样的引用不会使 myChild 引用的 object 保持存活,并且当 object 死亡时将自动设置为 nil