如何最好地为 ARC 代表保留自我?
Posted
技术标签:
【中文标题】如何最好地为 ARC 代表保留自我?【英文标题】:How best to retain self for delegate with ARC? 【发布时间】:2013-08-06 20:54:56 【问题描述】:想象三个班级。 ClassA 和 ClassB 是我的。第三类是 UIViewController,我不能修改它的代码:
在A类中:
- (void) aMethod
ClassB *classBInstance = [[[ClassB alloc] init] goWithOptions:options];
ClassBInstance
仅在 aMethod
的生命周期内保留。
在 B 类中:
- (void) goWithOptions
AUIViewController *avcInstance = [[AUIViewController alloc] init];
avcInstance.delegate = self;
[viewController pushViewController:avcInstance animated: YES]; // this returns immediately, but we need self to be retained until the delegate is done with it
- (void) cleanupCalledByDelegate //
// cleanup
当-goWithOptions
方法被调用时,avcInstance
被被调用者保留,但是传递给delegate
的self却没有。这意味着只要-goWithOptions
返回,并且aMethod
完成,那么classBInstance
就会被释放,而avcInstance
的delegate
将不再有效。
理想情况下,我想将classBInstance
(属于B 类的自己)的所有权绑定到avcInstance
;当avcInstance
被释放时,classBInstance
或委托被释放。
或者,我可以在 -cleanupCalledByDelegate
中清理 classBInstance
,它在 avcInstance
被释放之前调用。
如何最好地处理这个问题?我宁愿不让ClassB *classBInstance
成为ClassA 的属性,因为那样我就必须让它释放classBInstance
,我更愿意在ClassB 中处理它。如果这是最好的解决方案,我会使用块并在 ClassA 中传递一个完成块:
classBInstance = nil;
到-goWithOptions
,我会打电话给-cleanupCalledByDelegate
。这是处理这个问题的正确方法吗?
【问题讨论】:
arc 的一个缺点是你没有太多的控制权。保留/释放现在与属性相关联。要保留/释放某些内容,您必须添加另一个属性。 @JustinMeiners - 不仅仅是属性。强大的 ivars 也适用于范围和关联。 @TomSwift 对,关键是,它现在绑定到一个命名变量,使得解决这类问题变得更加麻烦。 【参考方案1】:如果你只是想“将classBInstance(ClassB中的self)的所有权绑定到avcInstance”,可以使用objective-c对象关联:
#import <objc/runtime.h>
objc_setAssociatedObject( avcInstance, "my_association", classBInstance, OBJC_ASSOCIATION_RETAIN );
此外,如果您以后需要更方便地访问 classBInstance,您可以将此关联代码包装到一个类别扩展中,该扩展将 classBInstance 公开为 avcInstance 上的一个属性。
【讨论】:
你可以这样做 (+1),但它闻起来像糟糕的应用程序设计。如果 ClassA 需要与 ClassB 建立比标准弱委托更正式的关系,则应将其建模为更正式的关系并显式管理。 但是ClassB不是需要与picker建立更正式的关系吗? A班只是想让某个班级完成一项任务,不想被如何打扰。 B 类需要将自身与需要委托但不保留委托的 UIViewController 选择器链接。 例如ClassA想要显示一些信息。它不关心它是如何显示的,也不关心显示是否成功。它打了个电话,然后愉快地前行。事实上,ClassA 可能想要进行许多这样的显示调用,并假设 ClassB 将管理队列——这意味着 ClassA 中的单个属性不是答案,我们要么依赖于在堆栈上创建唯一实例,要么创建和用于跟踪 ClassB 实例的数组属性。 由于 ClassB 决定它如何显示信息并且必须处理委托回调等,所以最好让 ClassB 和 UIViewController 处理保留,而不是将该任务暴露给另一个类. 我倾向于同意@bbum 的观点,即它“闻起来像糟糕的设计”,但这是你的决定。如果你只是务实并且可以证明你的模式是合理的,那么它可能没问题。 IMO,如果没有更多的洞察力,就很难做出判断。以上是关于如何最好地为 ARC 代表保留自我?的主要内容,如果未能解决你的问题,请参考以下文章