我在我的应用程序中使用以下模式并且正在过渡到 ARC。基本上,对象保留 Controller 的一个实例,并在通过委托(delegate)协议(protocol)通知它已完成时释放该 Controller 。我不使用 iVar/property b/c startProcess 可以调用 N 次来处理 N 件事。
下面的例子:
// start a process in a controller
- (void)startProcess
{
MyController *controller = [[MyController alloc] init];
// set the delegate, the delegate is defined as (nonatomic, assign)
controller.delegate = self;
[controller start];
}
// when the delegate is notified, release the controller
- (void)myControllerDidFinish:(MyController):controller
{
// do something with results
[controller release];
}
当上述实现转换为 ARC 时,
startProcess
结束后不再保留 Controller ,因此不会发生处理并且永远不会收到委托(delegate)消息。问题:将我的项目转换为使用 ARC 时,如何将上述实现修改为正常工作,而无需在实例化 Controller 的对象中创建 iVar?在 Apple 的文档中有一个类似的例子来过渡到 ARC,但它涉及使用块。我宁愿不用完成块替换委托(delegate)协议(protocol)。
编辑:在代码中添加了关于如何定义委托(delegate)的注释
编辑:澄清第一段以解释为什么持有 Controller 的 iVar/属性不起作用
最佳答案
通常,控制者有责任在完成任务时保留自己。如果您的 Controller 在后台线程上运行任务,那么它应该自动由 NSThread
的实例保留。如果使用 NSURLConnection
通过网络获取数据,则 Controller 应保留为 delegate
。
如果您没有执行这样的任务,则可以在执行任务时使用合成循环保留来保留 Controller 。这可以通过创建一个对象来完成,我称之为 ObjectRetainer
,它只有一个 __strong id
属性。当 Controller 开始其任务时,它应该有一个 __strong ObjectRetainer
实例变量,该变量被设置为保留 Controller 的新 ObjectRetainer
。这样, Controller 会保留一个 ObjectRetainer
来保留 Controller ,从而防止任何一个被释放。
当 Controller 完成其任务并调用了所有必要的委托(delegate)方法时,它应该将 ObjectRetainer
实例变量设置为 nil。这将释放 ObjectRetainer
,进而释放 Controller 。ObjectRetainer
接口(interface)可能如下所示:
@interface ObjectRetainer : NSObject {
__strong id object;
}
@property (nonatomic, strong) __strong id object;
@end
您应该在 Controller 的头文件中声明一个 ivar:
__strong ObjectRetainer _retainer
。然后,在 Controller 的 start
方法中:- (void)start {
...
_retainer = [[ObjectRetainer alloc] init];
_retainer.object = self;
}
Controller 完成后,只需将
_retainer
设置为 nil:- (void)performBackgroundTask {
....
[delegate myControllerDidFinish:self];
_retainer = nil;
}
关于objective-c - 在转换为 ARC 时,如何确保 Controller 在完成处理之前一直保留?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7869073/