想象一下以下情况:你有一个后台任务(这里的“任务”一词是指一个随机计算单元,而不是一个 NSTask!),它是使用任何现代技术实现的,例如 Grand Central Dispatch 或 Operation Queues。主线程上的某些控制器对象想要监视此后台任务的进度并将其报告给用户。
任务进度可以具有以下特征:
- 不确定或确定
因为控制器对象必须知道何时将 NSProgressIndicator 切换到适当的样式。我们可以使用一个约定,将进度视为不确定,直到实际进度值从零上升。 - 进度值本身
一个简单的浮点值 - 当前阶段
NSString 的本地化描述,因为与用户的通信良好
什么设计最适合这些要求,同时又是最可可的?
可以有变体。
代表团
在启动任务之前,将您的控制器对象设置为委托。
@protocol MyBackgroundTaskDelegate
@required
- (void) progress: (float) value; // 0.0…1.0
@optional
- (void) workingOn: (NSString*) msg; // @"Doing this, doing that…"
@end
其实这个模板我成功用过很多次了,但是感觉有点太啰嗦了。
阻止回调
与委托非常相似,但将代码保存在一个地方。
// 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 或轮询进度属性
在这种情况下,后台任务对象必须有两个类似于这些的属性:
@property(readonly, atomic) float progress;
@property(readonly, atomic) NSString* message;
并且客户端(我们的控制器对象)应该将自己设置为这些属性的观察者。我在这个解决方案中看到的主要缺陷是 KVO 通知总是到达导致更改的同一线程上。虽然您可以强制您的观察者(回调)方法在特定的 GCD 队列上运行,但它可能并不总是合适的。
NSNotificationCenter
后台任务发送通知,客户端监听它们。
还有其他适用于这种情况的模式吗?什么解决方案可以被视为最现代和可可的?