【问题标题】:How should delegator object lifespans be extended for the duration of a delegate callback?在委托回调期间应如何延长委托对象的生命周期?
【发布时间】:2012-11-19 22:29:11
【问题描述】:

我将把一个非常常见的情况提炼成一般形式。假设我正在构建一些关闭的库对象,执行一些异步工作,然后在完成后回调委托方法。现在,还出于某种任意原因说我不能使用 ARC 或块进行回调。这是老式的。我们称这个对象为 Worker。

现在说除了它的公共接口之外,各种应用程序中还有其他几个类对 Worker 一无所知。他们利用工人达到自己的目的。我们将这些类称为消费者。

Say Worker 像这样进行委托回调:

// "Private" method called internally when work is done.
- (void)somethingFinished
{
    [self.delegate workerDidFinish];
    [self someTask];
}

并且说一些特定的消费者像这样处理回调:

- (void)workerDidFinish
{
    // Assume "worker" is a retain property to a Worker
    // instance that we previously created and began working,
    // and that it's also the sender of the message.
    self.worker = nil;
    // Other code...
}

现在,如果没有其他方法保留该特定 Worker 实例,我们就有麻烦了。 Worker 将被释放,然后控制权将返回到其-somethingFinished 方法,然后它将-someTask 发送到回收或垃圾内存,并可能崩溃。没有人公然违反任何内存管理规则。

我不是在这里寻求技术解决方案。我知道几种选择。我想知道修复的责任落在谁身上。作为组件设计者,我是否应该实现 Worker 的 -somethingFinished 方法,以便在该方法的持续时间内延长 Worker 的生命周期,并在开头使用 [[self retain] autorelease] 之类的东西?或者,作为组件的消费者,我是否应该意识到我可能会在实例方法的中途吹走一个对象,然后等到稍后再释放它?

This question 的回答似乎都表明从回调中释放对象是一个坏主意。不幸的是,关于 Worker(在本例中为 CLLocationManager)究竟是如何传递给委托的,这个问题中有很多令人分心的信息,而我在这里故意避免了这些信息。 This question 遇到了同样的情况,并提供了另一种解决方案。

就我个人而言,我看不出消费者应该如何承担责任。它没有违反任何内存管理规则,并且礼貌地使用了 Worker 的公共接口。它只是在不再需要时释放一个实例。但另一方面,这是否意味着任何可能以某种方式在中间方法中被释放的对象都需要人为地延长其自身的生命周期?毕竟,委托方法并不是消息发送者最终在方法中间被释放的唯一方式。

那么最终,谁来负责修复?工人?消费者?可以规范地确定吗?

【问题讨论】:

    标签: objective-c memory-management object-lifetime


    【解决方案1】:

    我认为这个例子中的 Worker 是负担。我看到的问题是 Worker 对象在告诉其 Consumer 其工作已完成后正在内部做某事。 Worker 只是为了消费者而存在,所以如果消费者的目标得到满足,为什么 Worker 仍然在做对消费者没有价值的事情呢?如果在“消耗性”工作完成后需要完成内部任务,则这些任务不适合放置在 Worker 对象的实例中,但可能应该由易失性较小的库类拥有的另一个内部对象完成不会被消费者的行为解除分配。

    【讨论】:

    • 我认为说某些对象调用委托可能有理由进行后续内部调用一点也不为过。它们可以像清理程序一样简单。你是说不应该这样?
    • 是的,它不是一个延伸,但考虑到内存管理方案,我建议将清理/内部任务留给不会随消费者一时兴起而被破坏的对象可能是一种更好的模式和运行循环。
    【解决方案2】:

    当代理收到通知时,应该开始观察工作人员,并且只有在 somethingFinushed 方法终止时才释放它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 2018-11-11
      • 2011-01-19
      • 2013-04-18
      • 1970-01-01
      相关资源
      最近更新 更多