ios - for in 循环在内部是如何工作的 - Objective C - Foundation

标签 ios objective-c foundation for-in-loop fast-enumeration

我找到了这个答案:

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)时,你得到了一个错误

将“__strong id *”发送到“__unsafe_unretained_id*”类型的参数会更改指针的保留/释放属性

Screenshot of an error

但即使我关闭 ARC,我发现我的 __object 数组似乎表现得很奇怪:

Screenshot of error2

这是实际代码(我假设 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 时会出现该错误。

非常非常感谢您的时间和精力! (我提供了屏幕截图以更好地理解导致错误的原因)

最佳答案

首先,如“Transitioning to ARC Release Notes”中所述,C 结构中不能使用强指针,因此已声明对象数组 作为

__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" 中找到示例代码:

You have two choices when implementing this method:

1) Use the stack based array provided by stackbuf. If you do this, then you must respect the value of 'len'.

2) Return your own array of objects. If you do this, return the full length of the array returned until you run out of objects, then return 0. For example, a linked-array implementation may return each array in order until you iterate through all arrays.

In either case, state->itemsPtr MUST be a valid array (non-nil). ...

关于ios - for in 循环在内部是如何工作的 - Objective C - Foundation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20724712/

相关文章:

ios - 在不停止音乐播放的情况下在 iOS 上录制音频

ios - 计算 NSString 中 2 个单词之间的所有字符

iphone - 如何将动画实时链接/同步到视频录制

ios - UINavigationController - 使用 UIBlurEffect 清除背景

ios - 如何通过手指获取 UIScrollView 分页?

ios - xCode: Objective C: 重复符号错误

objective-c - 自动引用计数 (ARC) 和异步对象

ios - AFNetworking 处理来自 php 脚本的响应

objective-c - launchd 终止进程时是否调用了 XPC 中断处理程序?

ios - Xcode 8.1 "Provisioning profile doesn' t 包括 aps 环境授权”