-- 編集、以下の更新ソリューションを参照 --
ここには、バックグラウンド スレッドでデータをダウンロードするアプリがあります。
5 つのアイテムがダウンロードされるたびに、メイン ビュー コントローラーで、5 つのアイテムがダウンロードされたという通知を投稿します。
ナビゲーション スタックのルート ビュー コントローラーである他の 4 つのビュー コントローラーの 1 つで、詳細ページにドリルダウンします。(典型的な 5 つのタブ バー インターフェイス)
この詳細ページは、viewDidLoad メソッドに NSNotificationCenter defaultCenter addObserver を実行した別のビュー コントローラーです。
ここでの問題は、通知が投稿されると、詳細ページのルート ビュー コントローラーが通知を受け取りますが、詳細ページ自体は通知を受信しないことです。
データはバックグラウンド スレッドでダウンロードされていますが、ディスパッチ メソッドで performSelectorOnMainThread: を呼び出しています。ディスパッチ メソッドでは、[[NSNotificationCenter defaultCenter] postNotificationNamed:object:]; を呼び出します。
そう:
.... downloading batches of 5 items in a background thread ....
...
... downloaded calling [self performSelectorOnMainThread:@selector(foo) WithObject:nil WaitUntilDone:NO]; ...
...
// foo method
-(void)foo
{
// theoretically, this notification should be delivered and received in the main thread since this foo() method is told to execute on the main thread above
[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_batchDownloaded" object:nil];
}
...
ルート ビュー コントローラーで通知を受け取りますが、詳細ページでは受け取りません。
1) ダウンロード プロセスが開始されたとき、私は既に詳細ページを表示しているので、いいえ、詳細ページ ビュー コントローラーの割り当てが解除されているとは思いません
2) 詳細ページ ビュー コントローラーは明らかにメイン スレッドで通知を監視しており、前述のように、通知はメイン スレッドに投稿されるように指示されています。
問題は、サブレベルのビュー コントローラーが通知を受け取るのを妨げている他の理由があるのでしょうか?
通知オブザーバーの制限を超えたとは思いません。他の通知もコメントアウトしましたが、違いはありませんでした。
通知は 5 つのアイテムがダウンロードされるたびに送信されるため、通知が送信される前に詳細ページを表示する方法はありません。どういうわけか最初の 5 を逃したとしても、少なくとも 2 番目の 5、3 番目の 5、4 番目の 5 などを受け取る必要があります。
ルート ビュー コントローラーが最初に通知を受け取り、次にサブレベルのビュー コントローラーに通知を渡すことができなかった可能性がありますか?
私はアイデアがありません。
更新 - 犯人が見つかりました!
やっと壊れた場所が分かりました。なんというピタ。
以前の viewDidLoad メソッドでは、次のようにしました。
-(void)viewDidLoad
{
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"notif_batchDownloaded" object:@"notif_batchDownloaded"];
...
}
ここでの問題は、渡した「オブジェクト」パラメーターです。通知の名前を「オブジェクト」フィールドのパラメーターとして使用していますが、これにより doSomething() メソッドが実行されません。
object パラメータを削除したところ、動作するようになりました。
新しい viewDidLoad() は次のようになります。
-(void)viewDidLoad
{
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"notif_batchDownloaded" object:nil];
...
}
私はもともと、同じコールバック メソッドに複数の通知が送信された場合に、コールバック メソッドがどの通知が送信されたかを識別できるように、ある種のタグ付けのような「オブジェクト」パラメーターを使用できると考えていました。
Apple のドキュメントをざっと読むと、オブザーバーが通知を監視するオブジェクトを識別するために object パラメーターが使用されていることがわかります。つまり、複数のオブジェクトが同じ通知を送信できます。このオブジェクト パラメータ フィールドは、どのオブジェクトからのみ通知を受け取りたいかを識別します。
例えば
View Controller A と View Controller B はどちらも postNotificationName:@"notif_foo" です。
ビュー コントローラ C は、通知「notif_foo」のオブザーバとして自身を追加しますが、オプションで、ビュー コントローラ A をオブジェクト パラメータとして指定することにより、ビュー コントローラ A からのみ「notif_foo」を受信することを選択できます。
愚かな私は、通知コールバックメソッドで私が行くことができることに気づきませんでした:
if([notification name] isEqualToString:@"notifName"])
{
...
}
else
{
...
}
これが、この問題に頭を悩ませている他の人の助けになることを願っています。