什么是观察后台任务进度的可可方式?

Kon*_*hin 9 cocoa multithreading key-value-observing grand-central-dispatch

想象一下以下情况:你有一个后台任务(术语"任务"在这里意味着一个随机计算单元,而不是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
Run Code Online (Sandbox Code Playgroud)

实际上,我成功地使用了这个模板很多次,但感觉有点过于冗长.

阻止回调

与委托非常相似,但将代码保存在一个地方.

// 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;
    });
}];
Run Code Online (Sandbox Code Playgroud)

KVO或进展属性的轮询

在这种情况下,后台任务对象必须具有两个类似于以下的属性:

@property(readonly, atomic) float progress;
@property(readonly, atomic) NSString* message;
Run Code Online (Sandbox Code Playgroud)

客户端(我们的控制器对象)应该将自己设置为这些属性的观察者.我在这个解决方案中看到的主要缺陷是KVO通知总是到达导致更改的同一个线程.虽然您可以强制您的观察者(回调)方法在特定GCD队列上运行,但它可能并不总是合适的.

NSNotificationCenter

后台任务发送通知并且客户端侦听它们.

是否有其他适用于这种情况的模式?什么解决方案可以被视为最现代和可可?

小智 0

根据我的经验,委托或块回调是最好的设计选择。选择其中一种主要取决于哪一种更方便编码和支持特定情况。两者都是异步的。块回调通常会减少额外实例变量的必要性,因为块捕获其范围内的变量。当然,对于两者来说,都需要知道在哪个线程上执行回调或调用委托方法。