我真的很纠结于一个多线程程序,当外部变量发生变化时,它会改变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帖子,但我仍然感到困惑。
我真的很感谢你的帮助!
时间
发布于 2012-02-14 00:56:01
UI组件不是线程安全的。主线程使用run循环(参见NSRunLoop)调用您的代码(在此更改UI状态),然后在每次循环时更新屏幕。摆弄任何其他线程的UI组件都会把事情搞砸。
您需要将更改按钮标题/enabled的代码放在一个单独的方法中,并向主线程发出信号来调用它。你可以用performSelectorOnMainThread:withObject:waitUntilDone:做到这一点。这实际上创建了一个一次性的NSTimer,并安排它在主线程的run循环中立即触发,因此主线程将尽快调用该方法。
您可以选择挂起第二个线程,直到主线程完成调用(waitUntilDone:)。如果您只是在更新UI状态,我建议您不要等待,因为您不需要任何信息从UI传递回您的工作线程。
发布于 2012-02-14 00:37:24
你试过performSelectorOnMainThread吗?
[self performSelectorOnMainThread:@selector(doUIOnMainThread) withObject:nil waitUntilDone:NO];然后我的方法doUIOnMainThread做UI的事情。
https://stackoverflow.com/questions/9263380
复制相似问题