我找到了这个答案:
https://stackoverflow.com/a/5163334/1364174
介绍如何实现for in
循环。
NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
for (NSUInteger i = 0; i < __count; i++) {
id obj = __objects[i];
[obj doSomething];
}
}
问题是,我发现它错了。
首先,当您启用自动引用计数(ARC)时,出现错误
Sending '__strong id *' to parameter of type '__unsafe_unretained_id*' changes retain/release properties of pointer
但即使我关闭ARC,我发现__object数组似乎表现得很奇怪:
这是实际代码(我假设MAX_STACKBUFF_SIZE为40):
@autoreleasepool {
NSArray *myArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
int MAX_STACKBUFF_SIZE = 40;
NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
for (NSUInteger i = 0; i < __count; i++) {
id obj = __objects[i];
__enumState.itemsPtr
NSLog(@" Object from __objects ! %@", obj); // on screenshot different message
}
}
}
return 0;
当我尝试获取__object数组的内容时,我得到了EXC_BAD_ACESS。 我还发现,当你尝试迭代__enumState.itemsPtr它实际上是有效的。
你能解释一下这里发生了什么吗?为什么我的__objects
似乎“萎缩”了。为什么它不包含所需的对象?当ARC打开时,为什么会出现这种错误。
非常感谢您的时间和精力! (我提供了截图,以便更好地了解导致错误的原因)
答案 0 :(得分:3)
首先,强大的指针不能用在C结构中,如“转换到ARC发行说明”中所述,因此必须声明对象数组 如
__unsafe_unretained id __objects[MAX_STACKBUFF_SIZE];
如果使用ARC编译。
现在对NSFastEnumeration
文档来说(对我来说)并不明显,但确实如此
在Cocoa With Love:Implementing countByEnumeratingWithState:objects:count:中解释
实现不需要填充提供的对象数组,但可以设置
__enumState.itemsPtr
到现有阵列(例如某些内部存储)。在那种情况下,内容
__objects
数组未定义,导致崩溃。
更换
id obj = __objects[i];
通过
id obj = __enumState.itemsPtr[i];
给出预期结果,这是您观察到的结果。
另一个参考资料可以在"FastEnumerationSample"示例代码中找到:
实施此方法时有两种选择:
1)使用堆栈 由stackbuf提供的基于数组的数组。如果你这样做,那么你必须这样做 尊重'len'的价值。
2)返回自己的对象数组。如果 你这样做,返回返回的数组的全长,直到你 用完对象,然后返回0.例如,一个链接数组 实现可以按顺序返回每个数组,直到您进行迭代 通过所有数组。
在任何一种情况下,
state->itemsPtr
必须是有效的 数组(非零)。 ...