我相信您缺少的关键是NSProgress
该类旨在用作进度对象树。此外,这棵树是使用子进度对象隐式创建的,不需要知道它们附加到父级,这就是它真正强大的地方。
我发现 OS X Foundation Release Notes 比类参考更有帮助NSProgress
:
https://developer.apple.com/library/Mac/releasenotes/Foundation/RN-Foundation/index.html
处理程序似乎可用于 UI 控制器逻辑和数据控制器逻辑的原因是,当您构建父子层次结构时,您有两组可用于两者的处理程序。父处理程序将设置在 UI 控制器级别(进度的“消费者”),子处理程序将由数据控制器(“提供者”)设置。
由于可以使用becomeCurrentWithPendingUnitCount:
子进程对象隐式创建关系,因此将与父进程对象隔离,这将减轻您对客户端用他们自己的覆盖任何数据级处理程序的担忧。
在进度对象上调用pause
或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
});
}
请注意,我实际上并没有做过任何这些,这都是阅读文档的理论。