あなたが見逃している鍵は、NSProgress
クラスが進捗オブジェクトのツリーとして使用されるように設計されていることだと思います。さらに、このツリーは、親にアタッチされていることを認識する必要のない子の進行状況オブジェクトを使用して暗黙的に作成されます。これが真の力の源です。
OS X Foundation のリリース ノートは、次のクラス リファレンスよりもはるかに役立つことがわかりましたNSProgress
。
https://developer.apple.com/library/Mac/releasenotes/Foundation/RN-Foundation/index.html
ハンドラーが UI コントローラー ロジックとデータ コントローラー ロジックの両方に使用できるように見える理由は、親子階層を構築すると、両方に使用できる 2 つのハンドラー セットがあるためです。親のハンドラーは UI コントローラー レベル (進行状況の「コンシューマー」) で設定され、子のハンドラーはデータ コントローラー (「プロバイダー」) によって設定されます。
子の進行状況オブジェクトを使用して暗黙的に関係を作成できるため、becomeCurrentWithPendingUnitCount:
親から隔離されます。これにより、クライアントがデータレベルのハンドラーを独自のもので上書きするという懸念が軽減されます。
pause
進行中のオブジェクトでorを呼び出すcancel
と、その呼び出しがツリーに伝搬され、途中でハンドラーが呼び出されます。
例:
// UI controller level, probably a UIViewController subclass.
- (void)handleDoSomethingButtonTapped:(UIButton *)sender
{
self.progressThatWeObserve =
[NSProgress progressWithTotalUnitCount:100]; // 100 is arbitrary
self.progressThatWeObserve.pausingHandler = ^{
// Update UI, reflect paused state ...
};
[self.progressThatWeObserve becomeCurrentWithPendingUnitCount:100];
[self.dataController doSomethingInBackgroundWithCompletionHandler:^{
// Update UI, remove from view ...
}];
[self.progressThatWeObserve resignCurrent];
}
// Data controller level, a SomethingManager class maybe.
- (void)doSomethingInBackgroundWithCompletionHandler:(void (^)(void)completionHandler
{
self.progressThatWeManipulate =
[NSProgress progressWithTotalUnitCount:289234]; // e.g. bytes to upload
self.progressThatWeManipulate.pausingHandler = ^{
// Actually suspend the network operation ...
};
dispath_async(self.workerQueue, ^{
// Periodically update progress
});
}
私は実際にこれを行っていないことに注意してください。これはすべて、ドキュメントを読んだことによる理論です。