次の状況を想像してみてください: バックグラウンド タスク (ここでの「タスク」という用語は、NSTask ではなく、ランダムな計算単位を意味します) があり、Grand Central Dispatch や Operation Queues などの最新のテクノロジを使用して実装されています。メイン スレッドの一部のコントローラー オブジェクトは、このバックグラウンド タスクの進行状況を監視し、それをユーザーに報告したいと考えています。
タスクの進行状況には、次の特徴があります。
- コントローラ オブジェクトは、NSProgressIndicator を適切なスタイルに切り替えるタイミングを認識している必要があるためです。
実際の進行状況の値がゼロから増加するまで、進行状況が不確定なものとして扱われるという規則を使用できます。 - 進捗値自体
単純な float 値 - ユーザーとのコミュニケーションが良好であるため、現在のフェーズの NSString のローカライズされた説明
最も Cocoa らしく、これらの要件に最適なデザインはどれですか?
バリアントが存在する可能性があります。
委任
タスクを起動する前に、コントローラー オブジェクトをデリゲートとして設定します。
@protocol MyBackgroundTaskDelegate
@required
- (void) progress: (float) value; // 0.0…1.0
@optional
- (void) workingOn: (NSString*) msg; // @"Doing this, doing that…"
@end
実際、このテンプレートを何度も使用して成功しましたが、少し冗長すぎるように感じます。
コールバックをブロックする
委任に非常に似ていますが、コードを 1 か所に保持します。
// Starting our background task...
[MyTask startComputationWithProgressHandler: ^(float progress, NSString* msg)
{
// Switching to the main thread because all UI stuff should go there...
dispatch_async(dispatch_get_main_queue(), ^()
{
self.progressIndicator.progress = progress;
self.informationalMessage = msg;
});
}];
KVO または進捗プロパティのポーリング
この場合、バックグラウンド タスク オブジェクトには、次のような 2 つのプロパティが必要です。
@property(readonly, atomic) float progress;
@property(readonly, atomic) NSString* message;
クライアント (コントローラー オブジェクト) は、これらのプロパティのオブザーバーとして自分自身を設定する必要があります。このソリューションで見られる主な欠陥は、KVO 通知が、変更を引き起こした同じスレッドに常に到着することです。オブザーバー (コールバック) メソッドを特定の GCD キューで強制的に実行することはできますが、常に適切であるとは限りません。
NSNotificationCenter
バックグラウンド タスクが通知を送信し、クライアントが通知をリッスンします。
この状況に適用できる他のパターンはありますか? 最もモダンで Cocoa っぽいものとして扱うことができるソリューションはどれですか?