如何在循环内部工作 – 目标C – 基础
我find了这个答案:
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
但即使当我closuresARC时,我发现我__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打开时出现这种错误。
非常感谢您的时间和精力! (我提供了截图,以便更好地了解是什么导致错误)
首先,强指针不能在C结构中使用,如“转换到ARC版本注释”所述,因此对象数组被声明为
__unsafe_unretained id __objects[MAX_STACKBUFF_SIZE];
如果你用ARC编译。
现在对NSFastEnumeration
文档来说,这并不明显,但是在Cocoa With Love中有解释:实现countByEnumeratingWithState:objects:count:实现不需要填充提供的对象数组,但是可以将__enumState.itemsPtr
设置为现有的arrays(例如一些内部存储)。 在这种情况下, __objects
数组的内容是未定义的,导致崩溃。
更换
id obj = __objects[i];
通过
id obj = __enumState.itemsPtr[i];
给出预期的结果,这是你观察到的。
另一个参考可以在“FastEnumerationSample”示例代码中find:
实施此方法时您有两个select:
1)使用stackbuf提供的基于栈的数组。 如果你这样做,那么你必须尊重'len'的价值。
2)返回你自己的对象数组。 如果这样做,则返回返回数组的全部长度,直到用完对象,然后返回0.例如,链接数组实现可能会按顺序返回每个数组,直到遍历所有数组为止。
在任何一种情况下,
state->itemsPtr
务必是一个有效的数组(非零)。 …