104

私はObjectiveCクラスを持っています。その中で、initメソッドを作成し、その中にNSNotificationを設定しました

//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(getData)
                                             name:@"Answer Submitted"
                                           object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self]このクラスのどこに設定しますか?UIViewControllerについては、メソッドに追加できることを知ってviewDidUnloadいます。それでは、Objective Cクラスを作成した場合、何をする必要がありますか?

4

14 に答える 14

112

一般的な答えは、「通知が不要になったらすぐに」です。これは明らかに満足のいく答えではありません。

オブザーバーをクリーンに登録解除する最後のチャンスであるため、オブザーバーとして使用する予定のこれらのクラスの呼び出し[notificationCenter removeObserver: self]メソッドを追加することをお勧めします。deallocただし、これは通知センターが死んだオブジェクトに通知することによるクラッシュからあなたを保護するだけです。オブジェクトが通知を適切に処理できる状態になっていない/なくなっている場合、通知の受信からコードを保護することはできません。これについては...上記を参照してください。

編集(答えは私が思っていたよりも多くのコメントを描くように見えるので)ここで私が言おうとしているのは、通知センターからオブザーバーを削除するのが最適な時期について一般的なアドバイスを与えるのは非常に難しいことです。

  • ユースケースについて(どの通知が監視されますか?いつ送信されますか?)
  • オブザーバーの実装(通知を受信する準備ができているのはいつですか?準備ができていないのはいつですか?)
  • オブザーバーの意図された寿命(ビューまたはビューコントローラーなど、他のオブジェクトに関連付けられていますか?)
  • ..。

だから、私が思いつくことができる最高の一般的なアドバイス:あなたのアプリを保護すること。少なくとも1つの考えられる失敗に対して、removeObserver:ダンスをdealloc実行します。これが(オブジェクトの人生における)最後のポイントであり、それをきれいに実行できるからです。これが意味しないのは、「dealloc呼び出されるまで削除を延期するだけで、すべてがうまくいく」ということです。代わりに、オブジェクトが通知を受信する準備ができなくなったら(または必要でなくなったら)、オブザーバーを削除します。それはまさに正しい瞬間です。残念ながら、上記の質問の答えがわからないので、その瞬間がいつになるかは推測できません。

オブジェクトはいつでも安全にremoveObserver:複数回実行できます(特定のオブザーバーとの最初の呼び出しを除くすべてがnopsになります)。したがって、念のために(もう一度)dealloc実行することを検討してください。ただし、何よりもまず、適切なタイミングで実行してください(ユースケースによって決まります)。

于 2011-06-24T14:32:18.493 に答える
39

iOS 9 以降、オブザーバーを削除する必要はなくなりました。

OS X 10.11 および iOS 9.0 では、NSNotificationCenter および NSDistributedNotificationCenter は、割り当てが解除される可能性のある登録済みオブザーバーに通知を送信しなくなりました。

https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter

于 2016-04-24T11:23:35.703 に答える
39

注:これはテスト済みで、100% パーセント動作しています

迅速

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)
    
    if self.navigationController!.viewControllers.contains(self) == false  //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.
        
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

提示されたViewController:

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)
    
    if self.isBeingDismissed()  //presented view controller
    {
        // remove observer here
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

Objective-C

では、メソッドが非推奨になっiOS 6.0 > versionたため、オブザーバーを削除することをお勧めします。viewWillDisappearviewDidUnload

 [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];

remove observerビューが から削除されたときの方がよい場合が多くありnavigation stack or hierarchyます。

- (void)viewWillDisappear:(BOOL)animated{
 if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.
        
        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}

提示されたViewController:

- (void)viewWillDisappear:(BOOL)animated{
    if ([self isBeingDismissed] == YES) ///presented view controller
    {
        // remove observer here
        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}
于 2013-04-11T05:26:29.363 に答える
25

オブザーバーをビューコントローラーに追加する場合は、オブザーバーをに追加したり、viewWillAppearで削除したりすることを強くお勧めしviewWillDisappearます。

于 2012-08-08T15:27:11.830 に答える
20
-(void) dealloc {
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
}
于 2011-06-24T14:35:29.760 に答える
7

一般的に、私はそれをdeallocメソッドに入れます。

于 2011-06-24T14:31:34.127 に答える
5

私の意見では、次のコードはARCでは意味がありません。

- (void)dealloc
{
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
}

iOS 6では、オブザーバーを削除しても意味がありviewDidUnloadません。これは、現在非推奨になっているためです。

要約すると、私はいつもでそれをしviewDidDisappearます。ただし、@ Dirkが言ったように、要件によっても異なります。

于 2013-01-16T05:51:15.923 に答える
5

*編集: このアドバイスは iOS <= 5 に適用されます (そこでも追加viewWillAppearおよび削除する必要がありますviewWillDisappear- ただし、何らかの理由で にオブザーバーを追加した場合はアドバイスが適用されますviewDidLoad)

オブザーバーを追加した場合viewDidLoadは、 と の両方で削除する必要がdeallocありviewDidUnloadます。そうしないと、後でviewDidLoad呼び出されたときに 2 回追加することになりますviewDidUnload(これは、メモリ警告の後に発生します)。これは、非推奨で呼び出されない iOS 6 では必要ありviewDidUnloadません (ビューが自動的にアンロードされなくなったため)。

于 2012-11-25T12:17:21.653 に答える
4

信頼できる答えを見つけたと思います!上記の答えはあいまいで矛盾しているように見えるので、そうしなければなりませんでした。クックブックとプログラミングガイドに目を通しました。

addObserver:まず、親View Controllerでコードを実行するために子View Controllerに通知を投稿しているため、 inviewWillAppear:removeObserver:inのスタイルがviewWillDisappear:機能しません(テストしました)。同じView Controller内で通知を投稿してリッスンしている場合にのみ、このスタイルを使用します。

私が最も信頼する答えは、iOS Programming: Big Nerd Ranch Guide 4th にあります。彼らには iOS トレーニング センターがあり、別のクックブックを書いているだけではないので、私は BNR の人たちを信頼しています。正確であることは、おそらく彼らの最大の関心事です。

BNR の例 1: addObserver:in init:, removeObserver:indealloc:

BNR の例 2: addObserver:in awakeFromNib:, removeObserver:indealloc:

dealloc:…使用していないオブザーバーを削除する場合[super dealloc];

これが次の人に役立つことを願っています…</p>

Apple は現在ほぼ完全にストーリーボードを使用しているため、この記事を更新しています。そのため、上記がすべての状況に当てはまるとは限りません。重要なこと (そして最初にこの投稿を追加した理由) は、自分viewWillDisappear:が呼び出された場合に注意を払うことです。アプリケーションがバックグラウンドに入ったとき、それは私のためではありませんでした。

于 2014-06-13T13:44:19.223 に答える
2

受け入れられた回答は安全ではなく、メモリ リークを引き起こす可能性があります。登録解除を dealloc のままにしておくだけでなく、viewWillDisappear でも登録解除してください (もちろん、viewWillAppear に登録する場合です)。:)

于 2013-06-27T20:03:08.663 に答える