如何在委托回调期间扩展委托者对象生命周期?

时间:2012-11-19 22:29:12

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

我要将一种非常普遍的情况提炼成一般形式。假设我正在构建一些关闭的库对象,执行一些异步工作,然后在完成时回调委托方法。现在,也有一些随意的说法,我不能使用ARC或块来进行回调。这是老式的。我们将此对象称为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方法,以便在开始时使用类似[[self retain] autorelease]的方法延长工作者的生命周期?或者,作为组件的使用者,我是否应该知道我可能会在实例方法中途吹走一个对象,并等到稍后才释放它?

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

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

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

当委托得到通知时,应该开始观察工作人员并仅在终止某个方法时释放它。