3

我们有一个错误,它破坏了我们 UI 的外观,一些 UI 元素重叠,或者被添加到子视图中两次。该错误几乎无法重现,因此很难修复。现在我想到了原因,可能是同时调用了两次更改UI的方法。我是对的,我试图以编程方式创建错误。

我们有一个错误,这是由不同线程同时访问的方法引起的。模拟这个问题,更好地理解它。请参阅下面发布的代码。

当我这样做时,updatePresence 方法调用,我的程序完美运行

视图控制器.m

-(void)loadConversationScreen{
    [conversationController updatePresence];
}

但是当我这样做时,我的程序出了点问题

视图控制器.m

-(void)loadConversationScreen{
    [conversationController performSelectorInBackground:@selector(updatePresence) withObject:nil];
    [conversationController updatePresence];

}

这是因为该方法正在同时被访问,并且我的 UIView 的实例也在同时被访问/更改。

如何正确阻止 2 个线程同时使用一个方法?

我如何在 IOS 中正确处理它(如果没有正确的方法,有什么解决方法),是否有内置锁或某种东西?

我的应用程序应该支持 ios 4.0 及更高版本

提前感谢大家的帮助。

4

2 回答 2

6

最适合您的线程锁是@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];
    }
}

为了后代,因为我在阅读您的说明之前已经输入了它,如果您真的只关心更新 UI,您可能希望将您的调用强制转到主线程,而不是像这样:

- (void)someTask {
    dispatch_async( dispatch_get_main_queue(), ^{
        [self updateUI];
    });
}

- (void)updateUI {
    NSAssert( [NSThread isMainThread], @"called from non-main thread" );
    // do UI updates here
}
于 2012-07-05T06:54:51.637 回答
2

正如warrenm所说,您不应该UIView从与主线程(UI线程)不同的线程更新您的线程。不过,您问是否有任何解决方法可以解决正在发生的事情。老实说,您应该尝试理解为什么方法被调用两次,而不是阻止第二个线程访问您的方法。这比其他任何事情都更符合逻辑,您应该尝试解决这个问题,而不是尝试捷径。

于 2012-07-05T06:54:10.130 回答