gpt4 book ai didi

objective-c - 为什么这个 block 在创建时不捕获变量值

转载 作者:行者123 更新时间:2023-12-04 02:42:29 26 4
gpt4 key购买 nike

我在使用 GCD 的 Objective-C 中遇到以下问题,我无法弄清楚:

我正在使用以下方法计算大约 648 个图 block 的值。首先处理哪些图 block 的顺序由设置变量“pi”的某种算法给出。变量“loaded”在此上下文中是全局变量,从 0 开始并正确地上升到 647。

不使用积木时一切正常。

while (loaded < [self.tiles count]) {
long pi = /* tricky way to calculate the position index to set */;
NSLog(@"loaded: %d", loaded);
// Do this in a separate thread
dispatch_async(loader, ^{
NSLog(@"loaded ->: %d", loaded);
[self.tiles[loaded] setPositionIndexTo:pi];
});

loaded++;
}

问题:

我得到一个异常,因为该 block 试图访问 self.tiles[648]!在 Apple 的 block 文档中说, block 内变量的值在创建 block 时被捕获,所以我不明白,这怎么可能。我确实知道加载的变量实际上最终的值为 648,它应该在不执行的情况下中止循环。其他一些奇怪的是,值 0 也从未在 block 中使用过,但它以 1 开头。有时也可能看到该 block 在有关加载值的循环之前,有时根本没有值,或者做了两次。这是一些输出:

 loaded ->: 612
loaded: 613
loaded ->: 613
loaded ->: 614
loaded: 614
loaded ->: 614
loaded: 615
loaded: 616
loaded ->: 615
loaded: 617
loaded ->: 617

为什么以及如何做到这一点?

感谢您的任何澄清,正如我认为 Apple 的文档明确指出的那样,当创建 block 时,应该捕获“loaded”的值,而不再为 block 更改。

最佳答案

问题是 loaded 是实例变量,不是局部变量。 block 捕获本地 范围。在 Objective-C 中,当您访问实例变量时,编译器会将访问转换为结构成员访问。

@interface MyClass : NSObject
{
int varA;
}
@end

@implementation MyClass
- (void)someMethod
{
varA = 42; // This
self->varA = 42 // is actually this after compilation
}
@end

因此,该 block 在运行时将始终看到 loaded 的当前值,因为它实际上是在查看 self->loaded

这个问题有多种解决方案,但总的来说,您需要确保每个 block 看到loaded 的唯一值。一种简单的方法是使 loaded 成为局部变量。如果您需要跟踪总体进度,请更新 block 中的进度属性。 (请注意,如果 loader 是并发队列,则在更新 progress 属性时需要注意多线程问题。一个简单的解决方案是将更新分派(dispatch)回自定义串行队列。)

关于objective-c - 为什么这个 block 在创建时不捕获变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15117992/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com