在 Objective C 中为自定义类实现委托时的引用计数

Posted

技术标签:

【中文标题】在 Objective C 中为自定义类实现委托时的引用计数【英文标题】:Reference counting when implementing a delegate for custom class in ObjectiveC 【发布时间】:2009-06-08 18:36:26 【问题描述】:

我有两个类,ClassA 将实例化 ClassB 并将一个方法作为委托传递。 ClassB 最终将调用 ClassA 的委托。 ClassB存储的时候需要在ClassA上添加retain吗?

我正在遵循“Cocoa 基础指南:与对象通信”中的“实现自定义类的委托”,但演示的示例代码似乎没有考虑内存管理。

ClassA 将设置委托,并期望稍后在 ClassB 完成工作时回调。

@implementation ClassA

-(void)launchSomething

   ClassB *classB = [[ClassB alloc] init];
   [classB setCallback:self withSelector:@selector(deferredWork)];

   // do some other stuff, assign class B to some View and eventually release class B


-(void)deferredWork

   NSLog(@"this is the method that will be deferred till some point in time");

ClassB 的头文件,它将存储然后调用委托:

@interface ClassB

id targetObject;
SEL targetMethod;

-(void) setCallback:(id)anObject withSelector:(SEL)aMethod

ClassB 的实现:

@implementation ClassB
-(void) setCallback:(id)anObject withSelector:(SEL)aMethod

   // QUESTION: Do I need to add a 'retain' here on the targetObject?
   targetObject = anObject;
   targetMethod = aMethod;


-(void) someWorkLater

    if ( [targetObject respondsToSelector:@selector(targetMethod)] ) 
        // invoke the target object with the specific method
        [targetObject targetMethod];
    

【问题讨论】:

【参考方案1】:

您不会在 ClassB 中保留 ClassA,因为 ClassA 已经拥有 ClassB,并且假定当 ClassA 被释放时,它将负责清理 ClassB 中的所有引用。

如果您在 ClassB 中设置委托方法时遵循“正常”的所有权规则并保留 ClassA,那么您最终会得到一个保留循环,其中两个对象都不会被释放。相反,您应该像您一样使用弱引用。

【讨论】:

【参考方案2】:

正如 Marc 所说,Cocoa 中的正常做法是让代表成为“弱”链接。也就是说,它们不会被保留。由委托来确保当它不再能够作为委托进行响应时,不会发生任何不好的事情 - 通过将委托设置为 nil 或释放源对象(假设它是唯一的所有者并且将立即释放) .

因此,在您的示例中,如果 classB 在 launchSomething 结束后仍然存在,那么您可能已将其存储在 ivar 中。您的 classA 的 dealloc 例程要么有

[classB setCallback:nil]; // optionally withSelector:@selector(none)

和/或

[classB release];

如果 classB 可能有任何其他所有者,那么您绝对应该使用 setCallback:nil,但通常您知道您是唯一的所有者。

当涉及到视图和窗口时,事情会变得复杂,因为很难确保订单对象被释放,并且没有其他人与 classB 有强链接,在这种情况下,清除回调是必不可少的。

这同样适用于观察者和通知,它们通常是薄弱环节,在你的 dealloc 例程中会被清除。

【讨论】:

以上是关于在 Objective C 中为自定义类实现委托时的引用计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 app.config 中为自定义部分获取智能感知?

无法在 Bundle 中为自定义表格视图单元格类加载 NIB

Objective c - 为自定义 UITableViewCell 的按钮处理按钮触摸事件的最佳实践

如何在 Angular 中为自定义组件实现伪事件?

Objective-C 运行时委托问题

Objective c委托自我释放