来自GCD的线程读取旧值

时间:2012-04-16 21:14:02

标签: iphone objective-c ios

我的问题是我正在使用dispatch_async(dispatch_get_main_queue(), ^(void) { ... });异步调用方法,在此方法中,根据某些条件,我将布尔值设置为YES。当在此方法中读取此布尔值时,总是通过它的旧值NO读取。

奇怪的是,当我在检查布尔的线上做了一个断点时,一切都很顺利,按照预期进行!

编辑: 这是产生线程的代码

dispatch_async(dispatch_get_main_queue(), ^(void) {
    [self drawFaceBoxesForFeatures:features forVideoBox:claporientation:curDeviceOrientation image:img];
});

方法本身

- (void)drawFaceBoxesForFeatures:(NSArray *)features forVideoBox:(CGRect)clap orientation:    (UIDeviceOrientation)orientation image:(UIImage *)image;
{
    if (![self getSendingRequestStatus]) {
        NSLog(@"Sending req");
        // send async request

         dispatch_async(dispatch_get_main_queue(),^ {
             sendingRequest = YES;
         } );
      }
}

2 个答案:

答案 0 :(得分:3)

看起来您正在修改在块内部块之外创建的ivar。为了做到这一点并让ivar保持正确的值,您需要使用__block关键字,如下所示:

@interface MyCoolClass : NSObject {
    @private
    __block int sendingRequest_;
}

正如杰克劳伦斯在上面的推荐中所说,“[运行时]会拍摄当时所有相关对象/变量的快照”。 __block标识符将告诉运行时它不应该将该ivar复制到堆中,并允许您将值分配给块内的sendingRequest_,即使该块只是在主块上运行线程。

可以在Blocks Programming Guide找到许多好的信息(包括上述内容)。

答案 1 :(得分:1)

当基元传递到块中时,它们被复制。因此,如果您将一个原始的本地或实例变量放在一个块中,然后在创建块的相同方法(在块创建之后)或另一个方法中更改它,它将不会对块中的变量产生任何影响。对于局部变量,只需确保在创建块之前进行任何必要的更改。对于实例变量,您可以尝试使用某些C:self->iVar来访问实例变量,或者将其声明为属性并通过属性访问器访问它:self.iVar