20

AにはViewControllerがあり、(デリゲートとして)ViewControllerへの参照を持つ「ダウンローダー」オブジェクトを作成します。ダウンローダーは、アイテムのダウンロードに成功すると、ViewControllerをコールバックします。ビューにとどまっている限り、これは正常に機能しますが、ダウンロードが完了する前に移動すると、が表示されますEXC_BAD_ACCESS。これが発生している理由は理解できますが、オブジェクトがまだ割り当てられているかどうかを確認する方法はありますか?delegate != nil、、を使用してテストしようとしまし[delegate respondsToSelector:]たが、窒息します。

if (!self.delegate || ![self.delegate respondsToSelector:@selector(downloadComplete:)]) {
  // delegate is gone, go away quietly
        [self autorelease];
        return;
    }
else {
  // delegate is still around
  [self.delegate downloadComplete:result];
}

私はできることを知っています、

a)ダウンローダーオブジェクトにViewControllerを保持させる

b)View Controllerにダウンローダーの配列を保持し、ViewControllerの割り当てを解除するときにデリゲート値をnilに設定します。

しかし、デリゲートアドレスに有効なオブジェクトが含まれているかどうかをテストする、もっと簡単な方法があるのではないかと思います。

4

5 に答える 5

29

私はちょうどこの問題に遭遇し、それを解決しました。ARCの場合、解決策は。のweak代わりに属性を使用することですassign

デリゲートが原因でクラッシュが発生します

  1. 属性がありassign、AND
  2. 割り当てが解除されました。

weak解決策は、属性 を使用することです。これは、オブジェクトの割り当てが解除されると、ポインターがに設定されるためnilです。したがって、コードがを呼び出すrespondsToSelectornil、Objective Cはその呼び出しを無視し、クラッシュしません。

コードで、のrespondsToSelectorメソッドを呼び出そうとするとdelegate、EXC_BAD_ACCESSが取得されます。これは、assignプロパティを使用するオブジェクトnilは、割り当てが解除されたときにに設定されないためです。(したがって、!self.delegate前にを実行しても、割り当てが解除されたオブジェクトでが呼び出されるrespondsToSelectorのを妨げず、コードがクラッシュするのはなぜですか)responseToSelector

すでに述べたように、ARCでデリゲートにstrongorassign属性を使用すると(多くの人が言及しているように)、保持サイクルが発生します。だから、それをしないでください、あなたはする必要はありません。

于 2014-06-07T19:29:22.363 に答える
10

いいえ、「アドレスに有効なオブジェクトが含まれているかどうかを(便利に)テストする」ことはできません。メモリ割り当てシステムの内部をざっと見て、アドレスが有効なオブジェクトを指していると判断できたとしても、それが以前に参照していたのと同じオブジェクトであるとは限りません。オブジェクトは割り当てが解除され、同じメモリアドレスに別のオブジェクトが作成されました。

デリゲートを保持することは、これを解決するための通常の方法です。オプション(b)はオブジェクトのカプセル化を破り、スレッドセーフの問題が発生する可能性があります。

于 2010-04-21T03:52:35.063 に答える
1

私はただ書くだろう

SEL slc = @selector(theSlc);
if ([delegate respondsToSelector:slc]) {
    [delegate performSelector:slc];
}

オブジェクトが有効な場合はメソッドが呼び出され、そうでない場合は呼び出されません。あなたはチェックする必要はありません

self.delegate != nil
于 2010-04-22T11:33:05.557 に答える
1

私の「ダウンローダー」オブジェクトが私にEXC_BAD_ACCESSを与えていたので、私はこの質問に出くわしました。私の解決策は、ダウンローダーオブジェクトをリリースする直前にキャンセルすることでした。ダウンローダーオブジェクトでNSURLConnectionを使用していると仮定して、そのオブジェクトでcancelメソッドを呼び出します。

NSURLConnectionが現在何もダウンロードしていない場合、cancelを呼び出すとクラッシュすることに注意することが重要です。ダウンロードが進行中であるかどうかを確認するには、いくつかのロジックが必要になります。

于 2011-10-24T21:41:47.653 に答える
1

デリゲートの弱参照にも問題があります。現在、この問題の解決策は1つだけです。デリゲートに強参照を使用し、self.delegate=nilを手動で設定します。私のコードが完成した後。このソリューションは、非同期画像の読み込みで機能します。非同期画像の読み込みでは、目に見える終わりのあるライフサイクルがあります。

于 2013-07-24T12:07:28.813 に答える