我们遇到了一个错误,它破坏了我们UI的外观,一些UI元素重叠,或者已经被添加到子视图两次。这个bug几乎没有复制,所以很难修复它。现在我想到了原因,可能改变UI的方法同时被调用了两次。我是对的,我试图以编程方式创建错误。
我们有一个错误,它是由不同线程同时访问的方法引起的。要模仿这个问题,并更好地理解它。见下面张贴的代码。
当我执行此操作时,updatePresence方法调用,我的程序完美运行
ViewController.m
-(void)loadConversationScreen{
[conversationController updatePresence];
}
但是当我这样做时,我的程序出了问题
ViewController.m
-(void)loadConversationScreen{
[conversationController performSelectorInBackground:@selector(updatePresence) withObject:nil];
[conversationController updatePresence];
}
这是因为正在同时访问该方法,并且同时也正在访问/更改我的UIView实例。 击>
如何 正确 阻止两个线程同时使用某个方法?
如何在IOS中正确处理它(如果没有正确的方法,有什么工作),是否有内置锁或某些内容?
我的应用应该支持ios 4.0及更高版本
感谢所有人的帮助。
答案 0 :(得分:5)
最好的线程锁定是@sycnhronized(object) {}
。这意味着一次只能有一个线程输入代码。传入的对象用于执行锁定;只有一个线程可以进入受特定对象保护的块,一次同步。其他人会等。这可以是任何Objective-C对象,甚至是NSString
。
通常,您将使用您尝试保护的任何对象来保护多个线程。您可能需要@synchronized(self) {}
:
-(void)updateVariables {
@synchronized(self) {
_foo = 1;
_bar = 2;
}
}
@sycnhronized
是可重入的,因为同一个线程可以根据需要深入调用@sycnhronized
,例如:
- (void)a {
@synchronized(self) {
// entered "immediately" if called from b, where the @synchronized has
// already been called
_foo = _foo + 1;
}
}
- (void)b {
@synchronized(self) {
[self a];
}
}
对于后代而且因为我在阅读你的澄清之前已经输入了它,如果你真的只关心更新用户界面,你会想要强制你的主叫线程,而不是像这样:
- (void)someTask {
dispatch_async( dispatch_get_main_queue(), ^{
[self updateUI];
});
}
- (void)updateUI {
NSAssert( [NSThread isMainThread], @"called from non-main thread" );
// do UI updates here
}
答案 1 :(得分:2)
正如warrenm所说,你不应该从主线程(UI线程)以外的其他线程更新你的UIView
。不过,你问是否有任何解决方法可以解决的问题。说实话,你应该尝试,而不是阻止第二个线程访问你的方法,理解为什么方法被调用两次。这是一个比其他任何事情更合乎逻辑的问题,你应该尝试解决这个问题,而不是尝试快捷方式。