如何在循环内部工作 – 目标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数组似乎行为奇怪:

错误2的屏幕截图

这是实际的代码(我假设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务必是一个有效的数组(非零)。 …