さまざまなApple例(たとえば 音楽の追加 )を見ると、NSNotificationCenter
のデフォルトのviewDidLoad
にオブザーバーが追加されています。 、次にそれらをdealloc
で削除します。viewDidLoad
はdealloc
を呼び出さずに複数回呼び出すことができるため、これは危険なようです。これにより、同じオブザーバーが複数回追加され、ハンドラーが発生します。複数回呼び出されます。
これに対する解決策は、viewDidUnload
のオブザーバーも削除することですが、これは、同じオブザーバーがdealloc
でもう一度削除される可能性があることを意味し、潜在的な問題のようです。
何が足りないのですか?
正しい方法で通知を削除することについては、多くの議論があります。例えば:
viewWillDisappear
(またはviewDidDisappear
)およびviewDidUnload
ライフサイクルメソッドでオブザーバーを削除することをお勧めします。 (注:viewDidUnload
は非推奨であり、iOS6以降では実装しないでください。 iOS 6 --viewDidUnloadはdidReceiveMemoryWarningに移行します)を参照してください。 ? )
重要な注意:
viewDidUnload
が呼び出される保証はありません。これは標準のライフサイクルメソッドではありません。
From Apple doc:
viewDidUnloadメモリ不足の状態が発生し、現在のView Controllerのビューが不要な場合、システムはそれらのビューをメモリから削除することを選択する場合があります。このメソッドは、ビューコントローラのビューが解放された後に呼び出され、最終的なクリーンアップを実行するチャンスです。
代わりに、そのレシーバーの参照数がゼロの場合は常にdealloc
が呼び出されます。
それが役に立てば幸い。
編集
完全を期すために、 avoid-nsnotification-removeobserver の方法に関するこのリンクを参照してください。リンクは、オブザーバーを削除するためのいくつかの有用なガイドラインを提供します(コメントも参照してください)。 viewDidAppear
とviewDidDisappear
は多くのアプリケーションで常に正しく呼び出されるとは限らないため、作成者はviewWillAppear
/viewWillDisappear
メソッドでこれを行います。それはあなたの選択です。
オブザーバーを正しい方法で確実に削除したい場合は、dealloc
メソッドで登録を解除するか、2番目のコメントで書いたようにビューが完全にアンロードされたときに。ただし、dealloc
が将来呼び出されることを確認してください。言い換えると、すでに述べたように、他のオブジェクトが参照しているためにコントローラーが存続し続けると、メソッドが呼び出されることはありません。この場合、コントローラーは引き続き通知を受信します。
最近このページに出くわした人々にとって、オブザーバーの削除はもう必要ないかもしれません。 addObserver(_:selector:name:object:)
docs の「Discussion」セクションは次のように述べています。
アプリがiOS9.0以降またはmacOS10.11以降を対象としている場合、その
dealloc
メソッドでオブザーバーの登録を解除する必要はありません。それ以外の場合は、オブザーバーまたはこのメソッドに渡されたオブジェクトの割り当てが解除される前に、removeObserver(_:name:object:)
を呼び出す必要があります。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self .........]
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self .........];
}
なぜあなたはviewWillAppear
/viewDidDisappear
でそれをしないのですか?とにかくビューが表示されているときにのみ通知を気にしますよね?
ViewWillAppearでObserverを追加し、viewWillDisappearでObserverを削除できます。ただし、viewWillAppearは何度も呼び出される場合があります。したがって、最初に通知を削除してから、addObserverを削除できます。
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillShowNotification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillHideNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)name:@"UIKeyboardWillShowNotification"object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)name:@"UIKeyboardWillHideNotification"object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:YES];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillShowNotification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillHideNotification" object:nil];
}