2009-06-08 28 views
2

私は2つのクラス、ClassBをインスタンス化し、デリゲートとしてメソッドを渡すClassAを持っています。 ClassBは最終的にClassAの代理人を呼び出します。 ClassBに保存するときにClassAに保持を追加する必要がありますか?ObjectiveCでカスタムクラスのデリゲートを実装するときの参照カウント

"Cocoa Fundamentals Guide:オブジェクトとの通信"の "カスタムクラスの代理人の実装"に従っていますが、デモンストレーションされたサンプルコードではメモリ管理を考慮していないようです。

に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]; 
    } 
} 

答えて

2

あなたはClassBの中にClassAを保持しないだろう、なぜならClassAはすでにClassBを所有しており、ClassAの割り当てが解除されると、ClassB内の参照のクリーンアップが行われることが前提です。

ClassBでデリゲートメソッドを設定するときに、所有権の "通常の"ルールに従い、ClassAを保持すると、どちらのオブジェクトも割り当て解除されない保持ループになります。代わりに、まるであなたのように弱い参照を使うべきです。

0

Marc氏によると、Cocoaの通常の方法は、代理人が「弱い」リンクになることです。つまり、それらは保持されません。デリゲートをnilに設定するか、ソースオブジェクトを解放するか(それが唯一の所有者であり、すぐに解放されると仮定して)、デリゲートとして応答できなくなったときに、何も悪いことは起こりません。 。

あなたの例では、classBがlaunchSomethingの終了後に残っているとしたら、おそらくあなたはそれをivarに格納しています。クラスAのためのあなたのdeallocルーチンは

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

および/または

[classB release]; 

ClassBのは、その後、他の所有者を持っている可能性がある場合、あなたは間違いなくのsetCallback使用する必要があるだろう、次のいずれかnilを、しかし、多くの場合、あなたが唯一知っていますオーナー。

オブジェクトが解放され、誰かがclassBへの強いリンクを持っていないことを保証するのが難しい場合があるので、ビューとウィンドウが複雑になると、コールバックをクリアすることが不可欠です。

一般的に弱いリンクであり、deallocルーチンで多くクリアされるオブザーバと通知にも同じことが適用されます。

関連する問題