ほとんどのView Controllerに3人のオブザーバーを登録しています。いくつかはより多く、いくつかはより少ないが、私は登録と登録解除プロセスの一部を親クラスに含めたい。オブザーバーがいない場合でも、登録解除の呼び出しに問題はありますか?そして、3人のオブザーバーすべての登録を解除するだけで十分ですか?
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterBackground:)
name:UIApplicationWillResignActiveNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//Has to be unregistered always, otherwise nav controllers down the line will call this method
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
はい、オブザーバーがself
であるすべての登録を削除します。 NSNotificationCenter Class Reference に文書化されています。
次の例は、以前に登録したすべての通知の
someObserver
を登録解除する方法を示しています。[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
理論上(ただし、実際にはiOS 7.0の時点ではそうではありません)、UIViewController
にはviewWillDisappear:
で削除したくない独自の登録がある可能性があることに注意してください。 addObserver:selector:name:object:
を使用してパブリックAPIの通知に登録することはほとんどありません。これは、UIViewController
サブクラスに登録することを妨げるためです。将来のバージョンで。
登録を解除する安全な方法は、登録ごとにremoveObserver:name:object:
を1回送信することです。
- (void)deregisterForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[center removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
別の方法は、addObserverForName:object:queue:usingBlock:
の代わりにaddObserver:selector:name:object:
を使用して登録することです。これは、登録ごとに新しいオブザーバーオブジェクト参照を返します。これらを保存する必要があります(個々のインスタンス変数を作成したくない場合は、おそらくNSArray
インスタンス変数に保存してください)。次に、各通知をremoveObserver:
に渡して登録を解除します。例:
@implementation MyViewController {
NSMutableArray *observers;
}
- (void)registerForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *queue = [NSOperationQueue mainQueue];
__weak MyViewController *me = self;
observers = [NSMutableArray array];
[observers addObject:[center addObserverForName:UIKeyboardWillShowNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillShow:note];
}]];
[observers addObject:[center addObserverForName:UIKeyboardWillHideNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillHide:note];
}]];
[observers addObject:[center addObserverForName:UIApplicationWillResignActiveNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me applicationWillResignActive:note];
}]];
}
- (void)deregisterForKeyboardNotifications {
for (id observer in observers) {
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}
observers = nil;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
addObserverForName:object:queue:usingBlock:
によって返されるすべてのオブザーバーは、登録が1つだけの新しいオブジェクトであるため、removeObserver:
を呼び出すたびに、そのオブザーバーの1つの登録のみが削除されることが保証されます。
IOS 9およびmacOS 10.11では、オブザーバーの割り当てが解除されると、NSNotificationCenter
は自動的にオブザーバーの登録を解除します。デプロイメントターゲットがiOS 9以降またはmacOS 10.11以降の場合、dealloc
メソッド(またはSwiftのdeinit
)で手動で登録を解除する必要はありません。
オブザーバーがいない場合でも最初の質問の登録は解除できます。ただし、オブザーバーを削除する方法については、[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
は非常に推奨されないスーパークラスのオブザーバーも削除します(オブジェクトがアンロードされるためdeallocを除く)が、viewWillDisappear
ではオブザーバーを削除する必要があります[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
を使用して1つずつ