3

我在我的主线程中使用 NSProgressIndicator 在我运行整个方法时更新进度。现在,当我最终从不同的类文件中调用一个对象,并等待该对象返回到我的主线程的值时,我注意到 NSProgressIndicator 将消失。我知道这是因为主线程被阻塞,直到我从另一个对象获得返回值。

所以我的问题是在主线程中更新 UI 而不阻塞它并让其他对象在后台运行并根据需要将值返回给主线程的推荐方法是什么。我知道如何使用块,但不允许块操作返回值。我需要的是帮助这个伪代码的东西:

-(IBAction) main {

//Update progress indicator UI to show progress
//perform an call to another object from another class.
// wait till i get its return value.
//Update progress indicator UI to show progress
// Use this return value to do something.
//Update progress indicator UI to show progress


}

当调用另一个对象时,我注意到我已经完全消失了确定的 NSProgressIndicator,因为主线程被阻塞了。谢谢。

4

3 回答 3

9

您上面的代码不是正确的方法。由于main永不返回,进度指示器将永远不会更新。您必须在主线程上快速返回。

相反,您要做的是设置一个后台块,在各个点更新主线程上的进度指示器。因此,例如:

- (IBAction)start:(id)sender {
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  dispatch_async(queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:0];});

    // Doing some stuff
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:.25];});

    // Doing more stuff
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:.75];});
  });
}

(是的,这会导致队列保留self,但在这里没关系,因为self没有保留队列。)

于 2012-04-05T18:46:30.077 回答
4

您可以使用 GCD ( Grand Central Dispatch )实现您正在寻找的东西。

这是一个帮助您入门的示例:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        // Perform async operation
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // Update UI
                });
    });
于 2012-04-05T18:44:28.027 回答
0

听起来您的操作应该在单独的线程中运行,这可以通过多种方式完成,但使用 NSOperationQueue 和自定义 NSOperation 类(设置它们比听起来更容易)或使用 NSInvokeOperation 类可能最容易实现。

然后,您可以使用 NSNotificationCenter 在主线程中将消息发送回您的类,或者使用键值观察 (KVO) 将消息设置为观察者。

最重要的是,您有多种选择,并且要做出最好的选择,应该了解底层技术。我会亲自从 Apple 的Threaded Programming Guide开始,然后再读一遍,以确保在构建解决方案之前提取了所有优点。

于 2012-04-05T18:49:33.590 回答