使用enumerateKeysAndObjectsUsingBlock:方法,我能否确保它在同一个线程上被调用?

8

最近我在使用 enumerateKeysAndObjectsUsingBlock:,但今天我的一位同事指出这个枚举方法可以从单独的线程中调用,我的代码可能无法按预期工作。他甚至建议我使用快速枚举。问题是我真的很喜欢 enumerateKeysAndObjectsUsingBlock:,不喜欢快速枚举在处理字典时的工作方式。

我的方法如下所示:

- (NSArray *)someMethod
{
    __block NSMutableArray *myArray = [NSMutableArray array];

    [self.myDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [myArray addObject:obj];
    }

    return myArray;
}

我可以确定如果self.myDictionary不为空,那么myArray将始终返回预期的值,并且它将始终在与someMethod相同的线程上调用吗?
我知道有一个方法enumerateKeysAndObjectsWithOptions:usingBlock:,使用NSEnumerationConcurrent选项调用它将同时在多个线程上运行枚举。
但是我找不到任何关于enumerateKeysAndObjectsUsingBlock的文档。 同样适用于在数组上使用的enumerateObjectsUsingBlock:

1
你那么强烈地不喜欢快速枚举的"本质",以至于你宁愿使用这个你不确定的方法吗? - Jonathan Arbogast
在这里,你在块内存储数组的顺序是否重要? - Unheilig
通过“nature”,我指的是调用allKeys枚举它们,然后访问对象,而使用块枚举可以避免这种情况。块-更方便,代码更简单,也许在我的一端写得更少。 - PiotrDomo
@Unheilig,在这种情况下不是这样的。 - PiotrDomo
1个回答

8
正如您所观察到的,除非您使用 NSEnumerationConcurrent 选项调用 enumerateKeysAndObjectsWithOptions,否则可以确保它们不会并发执行。至于非并发版本的 enumerateKeysAndObjects 是否在同一线程上运行(尽管我敢打赌它确实如此),如果它没有在同一队列上运行,那么这对于您调用枚举方法的线程而言是同步运行的,因此并不重要。总之,您同事关于线程相关问题的担忧是没有根据的。
但是,我想指出的是,在我的经验测试中,这些枚举方法比快速枚举要慢。如果速度是最重要的(例如,特别是使用大型字典/数组时),则可能需要使用快速枚举。但在大多数情况下,差异并不显著。

1
我同意@Rob所说的。我想补充一下,enumerateKeysAndObjectsUsingBlock:实际上在内部调用enumerateKeysAndObjectsWithOptions:usingBlock:,并将0作为options参数传递。 - Hejazi
@Hejazi 你是怎么发现/知道的?请多给一点详细说明。谢谢。 - Unheilig
@Unheilig 我通过检查调用堆栈和寄存器发现了块执行时的情况。 - Hejazi
@Hejazi 我明白了,这在某种程度上听起来像是调用“指定构造函数”的事情,因此我才会问。再次感谢。 - Unheilig
1
@Unheilig 是的,没错。这是一种经验法则。没有代码被重写,所有重载(或便利)版本的方法最终都会调用一个方法(通常是具有最多参数的方法)。 - Hejazi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接