访问具有多个线程的UI组件

时间:2012-02-13 15:45:01

标签: iphone multithreading

我真的很挣扎于多线程程序,当外部变量发生变化时会改变IBOutlet。

使用类标题:

@interface QuestionViewController : UIViewController{

// IBOutlet
IBOutlet UIBarButtonItem *changeButton;

...

}

启动帖子:

    // Starts new thread with method 'statusPollMethod' to determine when status 
    [NSThread detachNewThreadSelector:@selector(statusPollMethod:) toTarget:self withObject: @"Voting"];

起始

-(void)statusPollMethod:requiredStatus{

GetSessionDataApi *statusPoll = [GetSessionDataApi new];
SessionCache *tempSessionCache = [SessionCache new];

...

@synchronized(self){
// Infinite Loop
while(1) {

    // If sessionStatus is 'Voting' set button as displayed
    if ([[tempSessionCache sessionStatus] isEqualToString: (@"Voting")]){
        NSLog(@"Status is Voting!");
        // Ungreys and sets the button
        [changeButton setTitle:@"Submit"];
            changeButton.enabled = YES; 
    }

    // Wait for around 3 seconds
    [NSThread sleepForTimeInterval:3]; 

    }
   }
   return;
}

问题是第二个线程偶尔会在IBOutlet上完成任何操作。 IBOutlet也可以通过第一个线程访问,所以我知道我可能有一些多线程问题而且我不确定如何保护IBOutlet。

据我所知,我查看了Apple Docs / Overflow帖子,但我仍感到困惑。

我真的很感谢你的帮助!

2 个答案:

答案 0 :(得分:1)

您是否尝试过performSelectorOnMainThread?

    [self performSelectorOnMainThread:@selector(doUIOnMainThread) withObject:nil waitUntilDone:NO];

然后我的方法doUIOnMainThread执行UI操作。

答案 1 :(得分:1)

UI组件不是线程安全的。主线程使用一个运行循环(参见NSRunLoop)调出你的代码(你改变UI状态),然后它在每次循环中更新屏幕。使用来自任何其他线程的UI组件进行混乱将会搞砸。

您需要在单独的方法中放置更改按钮标题/启用的代码,并通知主线程调用它。您可以使用performSelectorOnMainThread:withObject:waitUntilDone:执行此操作。这基本上创建了一次性使用的NSTimer,并安排它在主线程的运行循环中立即触发,因此主线程将尽快调用该方法。

您可以选择暂停第二个线程,直到主线程完成调用(waitUntilDone:)。如果您只是更新UI状态,我建议不要等待,因为您不需要将任何信息从UI传递回工作线程。