web-dev-qa-db-ja.com

iOS 5ARCでNSNotificationCenterオブザーバーを削除する

IOS 5 ARCベースのプロジェクトがあり、NSNotificationCenter内に登録したUIViewControllerオブザベーションのオブザーバーを削除する場所について問題があります。 SO)に関する同様の投稿では、これは-deallocメソッドで実行する必要があると述べています。このメソッドはARCプロジェクトでは必須ではありませんが、次のコードで追加しました。

- (void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

テストとして、UIViewControllerUINavigationController内)を開き、通知をトリガーするいくつかの操作を行ってから、[戻る]ボタンをタップしてスタックからポップします。次に、UIViewControllerを再度開き、通知をトリガーするためにさらにいくつかのことを行いますが、各コールバックが2回呼び出されていることに注意してください。これは、前の通知が登録解除されていないことを示しています。この手順を繰り返すと、各コールバックが複数回呼び出されるため、登録が解除されることはないように見えます。

どんな助けでもいただければ幸いです!

21
Skoota

deallocメソッドが呼び出されていないことは明らかです(removeObserver呼び出しも呼び出されていません)。

viewDidUnload:またはviewWillDisappear:メソッドでUIViewControllerのオブザーバーを削除してみませんか?

7

Deallocが呼び出されていない場合は、誰かがまだViewControllerへの参照を保持していることが原因である可能性があります。おそらく、何かを__weakとしてマークする必要がありますか?割り当てインスツルメントを使用して、ViewControllerに保持されているものを追跡するのに役立てることができます。

7
Jesse Rusak

「ビューが画面外にある場合でも通知コールバックを起動する必要があります」-> UIApplicationWillEnterForegroundNotificationを登録する必要がある場合があります。もしそうなら、これを試してみましょう:

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewWillAppear");
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidEnterBackground:)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"viewWillDisappear");
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"applicationWillEnterForeground");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidEnterBackground:)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    // do your stuff here
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"applicationDidEnterBackground");
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationWillEnterForeground:)
                                                 name:UIApplicationWillEnterForegroundNotification
                                               object:nil];
}

アイデアは、画面に出入りするたびにUIApplicationDidEnterBackgroundNotificationを追加または削除することです。アプリがバックグラウンドに入るときにUIApplicationWillEnterForegroundNotificationを登録し、戻ったら削除するだけです。 viewWillDisappearの場合、UIApplicationDidEnterBackgroundNotificationを削除するだけであることに注意してください。

私のdealloc()はどういうわけか呼び出されていないので、この方法を見つけました。あなたにも役立つことを願っています。

楽しい :)

3
thanhbinh84