我真的很挣扎于多线程程序,当外部变量发生变化时会改变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帖子,但我仍感到困惑。
我真的很感谢你的帮助!
添
答案 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传递回工作线程。