2009-07-01 15 views
13

クラスAがクラスBを使用し、クラスAがクラスBのデリゲートである場合、デリゲートがクラスBのdeallocでnilに設定されていればOKです?私は通常、クラスAのdealloc内のデリゲートをnilにリセットするコードを見たことがありますが、実際の違いが何かをしているかどうかは分かりませんでした。デリゲートをクラス内でnilに設定する必要がありますか?

これは通常の方法である:

// somewhere in class A 

- (void) someFunc { 
    self.b = [[B alloc] init]; 
    self.b.delegate = self; 
} 

- (void) dealloc { 
    self.b.delegate = nil; 
    [self.b release]; 
} 
+2

'self.b = [[B alloc] init];' b 'の '@ property'がretainの場合にRHSで' alloc'を使用している場合は、 'self'を使用しないでください。ちょうど追加したかった。 – thesummersign

+0

@geekay、なぜですか? –

+0

これは非アークの間でした – thesummersign

答えて

15

はい、あなたはクラスAののdeallocでnilにClassBののデリゲートのプロパティを設定する必要があります。

デリゲートプロパティは保持サイクルではなく、保持されないようにマークする必要があるため、メモリ管理の問題ではありません(それ以外の場合は、deallocは呼び出されません)。問題は、そうでなければ、classBは解放された後にclassAにメッセージするかもしれないということです。

たとえば、classBに「隠されている」というdelagate呼び出しがあり、classAの直後にclassBが解放されている場合は、すでにdeallocされたclassAにクラッシュが発生したというメッセージが表示されます。

また、自動解放されている場合は特に、deallocの順序を守ることはできません。

したがって、classAのdeallocのデリゲートプロパティは除外してください。

+1

+1メッセージングの可能性があるBについての良い点は、マルチスレッドのシナリオではおそらくそうですが、わかりません。 GCを使用している場合は、__weak参照のための素晴らしいアプリケーションの1つです。私はデリゲートが常に新しいコードで__weakであるべきだと思います。 –

+0

うん、これはマルチスレッドのアプリでこれに噛まれてしまった – marchinram

8

私の知る限りでは、あなたはこのような状況のためにカウントを保持上の循環参照を避けるようにそのベストプラクティス(割り当て)デリ​​ゲート、。あなたは、適切にプロパティを設定している場合、すなわち:

@property (assign) id<BDelegate> delegate; 

あなたはself.b.delegate =自己呼び出したときに保持カウントがぶつかっていないとして、にdealloc内の任意のメモリ管理を実行する必要はありません; - (保持)または(コピー)の使用とは異なり

意味がありますか?デリゲートを無制限に設定すると問題はありませんが、そのポイントは何ですか?

+0

+1それは正しいです、代議員はほとんど保持されるべきではありません。デリゲートが通常委譲するオブジェクトを保持するので、それは保持サイクルの古典的な原因です。 –

+3

クライアントが存在しなくなったデリゲートオブジェクトを呼び出そうとすると、クライアントがnilに設定されているためクラッシュしないため、デリゲートをnilに設定するという点があります。 – Boon

+0

デリゲートを含むクラスをdeallocしています...その時点でクラスのインスタンス化をメモリから削除している場合、オブジェクトに対して何らかのアクションを実行するとメモリアクセスエラーが発生しますその代理人を参照してください。ここに何かが見つからない限り... – Josh

5

まず、いくつかの観測...

  1. 独自のdeallocメソッドの最後で[super dealloc]を呼び出すために忘れてしまいました。
  2. 'b'が作成されていて、他のオブジェクトが 'b'を保持していない場合は、-deallocにデリゲートを記入する必要はありません。なぜなら、 'b'は何とか破壊されるからです。他のオブジェクトが 'b'への参照を持つ可能性がある場合(つまり、 'a'よりも長生きする可能性があることを意味する)、デリゲートをnilに設定します。
  3. オブジェクト 'b'は、デベロッパー自身の-dealloc を必要に応じて処理します。
  4. -init ...と-deallocメソッドでプロパティを使用しないようにする - Appleはこれを拒否しているのは正当な理由があるためです。 (予期せぬ副作用があるだけでなく、より厄介で厄介な問題を引き起こす可能性もあります)
  5. 余分な作業を不可視にする必要がない場合は、プロパティを使用します(ドット構文による)。たとえば、self.b.delegate = self[[self getB] setDelegate:self]に相当します。これは、あなたがivarに直接アクセスしているように見える構文的な砂糖ですが、実際にはそうではありません。
  6. これらの機能を理解せずにプロパティを使用すると、問題が発生する可能性があります。 self.bが値を保持している場合(プロパティが "assign"に設定されている)、手にメモリリークが発生します。

は、ここで私はおそらくそれを書くだろう方法は次のとおりです。

- (void) someFunc { 
    b = [[B alloc] init]; 
    b.delegate = self; // or [b setDelegate:self]; 
} 

- (void) dealloc { 
    b.delegate = nil; 
    [b release]; 
    [super dealloc]; 
} 
関連する問題