NSThread并更新子视图中的对象

时间:2011-04-18 14:19:11

标签: objective-c nsthread

在我的应用程序中,当我按下按钮时,我想要更新我的数据库。因为这项工作需要一些时间而不是冻结漏洞应用我决定使用NSThread。

此过程可以从不同的视图开始,因此我将更新代码放在我的App Delegate中。按下更新方法时,我有以下代码:

MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[NSThread detachNewThreadSelector:@selector(startTheBackgroundJob) toTarget:delegate withObject:nil];

在我的代表中:

- (void)startTheBackgroundJob {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//do some stuff here
    self.percentageCompleted = (i * 100) / totalChars;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshObjectsForUpdate" object:self];
//some other stuff
    [pool release];

基本上在我的线程中我想用当前进度更新不同的progressView。所以我使用NSNotificationCenter在我的线程的每一步之后发送消息。

在viewController中,我正在捕捉此消息,我正在做:

MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];

double prc = delegate.percentageCompleted;
UILabel *l = (UILabel *)[self.view viewWithTag:444];
l.text = [NSString stringWithFormat:@"%f", prc];

但它只在帖子的末尾刷新我的标签。

这是什么问题?我可以用另一种方法吗?

感谢。

2 个答案:

答案 0 :(得分:4)

来自Apple's documentation

  

在多线程应用程序中,通知始终在发布通知的线程中传递...

因此您需要执行代码以在主线程上明确更新UI(使用performSelectorOnMainThread:withObject:waitUntilDone:或任何合适的内容)。

答案 1 :(得分:2)

@paulbailey关于在主线程上执行选择器是正确的。我还要补充一点,如果你正在做的是高性能,我会完全避免使用通知中心。它将同步广播,这意味着每个循环迭代都会更新每个UI元素。您可以在performSelector方法上使用“waitUntilDone”标志使其异步,但是您可能会导致许多线程和上下文切换。

看看NSNotificationQueue并合并面具。您可以按照自己喜欢的方式发布,并且只会将通知合并到可以方便地发送它们。这当然具有较低的交付保证,因此您需要检查它是否会导致您的UI无法接受。