循环如何在内部工作 - 目标C - 基础 [英] How for in loop works internally - Objective C - Foundation

查看:103
本文介绍了循环如何在内部工作 - 目标C - 基础的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了这个答案:



示例代码:


实现此方法时有两种选择:



1)使用stackbuf提供的基于堆栈
的数组。如果你这样做,那么你必须
尊重'len'的价值。



2)返回自己的对象数组。如果
你这样做,返回返回的数组的全长,直到
用完对象,然后返回0.例如,链接数组
实现可以按顺序返回每个数组直到你通过所有数组迭代



在任何一种情况下, state-> itemsPtr 必须是有效的
数组(非零) )。 ...



I found this answer:

https://stackoverflow.com/a/5163334/1364174

Which presents how for in loop is implemented.

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];
    }
}

The problem is that, I found it wrong.

First of all, when you have Automatic Reference Counting (ARC) turned on, you got an error

Sending '__strong id *' to parameter of type '__unsafe_unretained_id*' changes retain/release properties of pointer

But even when I turn ARC off I found out that I __object array seems to behave strangely :

This is actual Code (I assumed MAX_STACKBUFF_SIZE to be 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;

I got EXC_BAD_ACESS when I try to get the contents of the __object array. I also found out that when you try to iterate through __enumState.itemsPtr it actually works.

Could you explain me what is going on here ? Why my __objects seems to be "shrunken down". And why it doesn't contains desired object? And why is that error when ARC is turned on.

Thank you very very much in advance for your time and effort! (I provided screenshot for better understanding what causes an error)

解决方案

First of all, strong pointers cannot be used in C-structures, as explained in the "Transitioning to ARC Release Notes", therefore the objects array has be be declared as

__unsafe_unretained  id __objects[MAX_STACKBUFF_SIZE];

if you compile with ARC.

Now it is not obvious (to me) from the NSFastEnumeration documentation, but it is explained in Cocoa With Love:Implementing countByEnumeratingWithState:objects:count: that the implementation need not fill the supplied objects array, but can just set __enumState.itemsPtr to an existing array (e.g. some internal storage). In that case, the contents of the __objects array is undefined, which causes the crash.

Replacing

id obj = __objects[i];

by

id obj = __enumState.itemsPtr[i];

gives the expected result, which is what you observed.

Another reference can be found in the "FastEnumerationSample" sample code:

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). ...

这篇关于循环如何在内部工作 - 目标C - 基础的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆