如何在iOS中从非UI线程更新UI标签

20
我是 iOS 开发新手,我有一个名为 "MoneyTimer.m" 的普通 Objective-C 类用于运行计时器,在那里我想通过计时器的变化值更新 UI 标签。 我想知道如何从非 UI 线程访问 UI 元素?我正在使用 Xcode 4.2 和 Storyboarding。
在黑莓上,只需获取事件锁即可从非 UI 线程更新 UI。
//this the code from MyTimerClass

 {...
    if(nsTimerUp == nil){

        nsTimerUp = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:@selector(countUpH) userInfo:nil repeats: YES];
 ...}

(void) countUpH {

sumUp = sumUp + rateInSecH;
 **//from here i want to update the UI label **
...
}

1
你可以从所有主线程更新 UI,但从后台线程更新 UI 会引起问题。 - rishi
5个回答

34

这是最快、最简单的方法:

- (void) countUpH{

   sumUp = sumUp + rateInSecH;
   //Accessing UI Thread
   [[NSOperationQueue mainQueue] addOperationWithBlock:^{

      //Do any updates to your label here
      yourLabel.text = newText;

   }];
}
如果您这样做,就不必切换到另一种方法。
希望这能帮到您。
Sam

@shoughton123,我可以在后台运行的方法中调用[[NSOperationQueue mainQueue] addOperationWithBlock:...吗?谢谢。 - JFS
当然可以,抱歉回复较慢! - shoughton123
请参考https://dev59.com/Jmkv5IYBdhLWcg3wkBka#10509159,了解addOperationWithBlock和performSelectorOnMainThread的行为差异。 - LordParsley

3
正确的方法是这样的:
- (void) countUpH  {
   sumUp = sumUp + rateInSecH;
   //Accessing UI Thread
   dispatch_async(dispatch_get_main_queue(), ^{

   //Do any updates to your label here
    yourLabel.text = newText;
   });
}

3

您的问题没有提供太多信息或细节,因此很难知道您需要做什么(例如是否存在“线程”问题等)。

无论如何,假设您的MoneyTimer实例具有对当前viewController的引用,您可以使用 performSelectorOnMainThread

//

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

抱歉缺乏细节,实际上我有一个继承自NSObject的Timer类,我想从那里更新一个放置在我的一个ViewController中作为属性的UILabel。现在我无法从我的Timer类访问UILabel。 - Jitendra kumar jha
为什么你不能访问它?在你的计时器类中添加一个委托属性,并在创建计时器实例时将要通信的视图控制器设置为委托。然后调用委托上的方法来更新标签。这是一个标准的iOS设计模式 - 值得了解一下。另外,只是为了好玩,你是否在计时器类中做其他工作?也许你过于面向对象了;-) - spring

2

我曾经做过完全相同的事情。

我使用了一个函数来设置标签文本:

- (void)updateLabelText:(NSString *)newText {
    yourLabel.text = newText;
}

然后使用performSelectorOnMainThread在主线程上调用此函数。

NSString* myText = @"new value";
[self performSelectorOnMainThread:(@selector)updateLabelText withObject:myText waitUntilDone:NO];

1

假设标签与同一类别一起存在:

    if(nsTimerUp == nil){
        nsTimerUp = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:@selector(countUpH) userInfo:nil repeats: YES];
    [self performSelectorOnMainThread:@selector(updateLabel)
                                           withObject:nil
                                        waitUntilDone:NO];

    }

-(void)updateLabel {
    self.myLabel.text = @"someValue";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接