アプリ内では、いくつかのビューコントローラーを使用しています。 1つのビューコントローラーでは、オブザーバーは次のように初期化されます。
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];
初期化前にNSNotification
を削除する場合でも、myMethod:
の実行回数は、それぞれのビューコントローラーで繰り返されるビューの数によって合計されます。
なぜこれが発生し、myMethod:を複数回呼び出さないようにすることができますか?.
注:postNotificationを複数回呼び出すときに間違いを犯さないように、ブレークポイントを使用して確認しました。
編集:これは私のpostNotificationがどのように見えるかです
NSArray * objects = [NSArray arrayWithObjects:[NSNumber numberWithInt:number],someText, nil];
NSArray * keys = [NSArray arrayWithObjects:@"Number",@"Text", nil];
NSDictionary * userInfo = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];
編集:サブスクリプションをビューに移動した後も表示されます:同じ結果が得られます。 myMethod:は複数回呼び出されます。 (ビューコントローラーをリロードした回数)。
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];
}
編集:ライフサイクルに問題があるようです。 ViewDidUnloadとdeallocが呼び出されていませんが、viewdiddisappearが呼び出されています。
ビューコントローラーをスタックにプッシュする方法は次のとおりです。親はテーブルビューサブクラスです(行をクリックすると、このビューコントローラーが開始されます:
detailScreen * screen = [[detailScreen alloc] initWithContentID:ID andFullContentArray:fullContentIndex andParent:parent];
[self.navigationController pushViewController:screen animated:YES];
解決:
Nsnotificationの削除をviewdiddisappearに移動するとうまくいきました。ご指導ありがとうございます!
この説明に基づくと、考えられる原因は、ビューコントローラーが過剰に保持され、意図したとおりに解放されないことです。これは、物事が過剰に保持されている場合、ARCでもかなり一般的です。そのため、特定のビューコントローラのインスタンスが1つだけアクティブであると考えていますが、実際にはいくつかのライブインスタンスがあり、それらはすべて通知をリッスンします。
私がこの状況にあった場合、ビューコントローラーのdeallocメソッドにブレークポイントを設定し、それがアプリの意図した設計である場合は、正しく割り当て解除されていることを確認します。
どの方法でオブザーバーを登録しましたか?
Appleは、オブザーバーをviewWillAppear:
に登録し、viewWillDissapear:
で登録解除することを推奨しています
オブザーバーを2度登録しなくてもよろしいですか?
Swiftを実行しているアプリケーションでこの問題に遭遇しました。アプリケーションは、最初の起動時に一度通知を受け取りました。通知により、バックグラウンドに戻って戻ってくる回数が増えます。つまり
解決策:アプリケーションがビューコントローラーでアクティブに辞任することを確認します。
NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationWillResign:", name: UIApplicationWillResignActiveNotification, object: nil)
func applicationWillResign(notification : NSNotification) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
これにより、ビューがバックグラウンドになったときに、ビューコントローラーが通知のオブザーバーを確実に削除します。
通知を購読している可能性が高いです
[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];
before selfが初期化されます。そして、実際にサブスクライブされていない 'self'をサブスクライブ解除しようとすると、すべてのグローバルmyNotification通知が表示されます。
ビューがIBに接続されている場合、通知を登録するための開始点として-awakeFromNib:を使用します
オブザーバーを持つクラスは、適切に複数回インスタンス化される可能性があります。デバッグ中は、通知が複数回投稿されているように見えます。しかし、self
を調べると、毎回異なるインスタンスであることがわかります。
アプリがタブバーを使用し、オブザーバーが、ビューコントローラーがサブクラスである基本クラスにいる場合、これは簡単に当てはまる可能性があります。