2013-12-21 41 views
5

找到這個答案:如何在循環的內部工作原理 - 目標C - 我基金會

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

呈現for in迴路是如何實現的。

​​

問題是,我發現它錯了。

首先,當你有自動引用計數(ARC)開啓時,你得到一個錯誤

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

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; 

我EXC_BAD_ACESS當我試圖讓__object數組的內容。 我還發現,當你嘗試遍歷__enumState.itemsPtr它實際上工作。

你能解釋一下這裏發生了什麼嗎?爲什麼我的__objects似乎被「縮小」了。爲什麼它不包含所需的對象?當ARC打開時,爲什麼會出現這種錯誤。

非常感謝您提前花費您的時間和精力! (我提供了屏幕截圖,以便更好地理解是什麼導致了錯誤)

+0

我不明白,爲什麼不直接使用'for in ___'? –

+1

@ 0x7fffffff我試着理解'for in'循環的實現。 –

+0

@bluesm不要直接從這個答案中得到代碼。它最好是僞代碼*。這幾乎不是編譯器的創建者如何實現循環。 – 2013-12-22 00:32:21

回答

3

首先,強指針不能用於C結構中,如「轉換到ARC版本註釋」中所述,因此要聲明對象數組 as

__unsafe_unretained id __objects[MAX_STACKBUFF_SIZE]; 

如果用ARC編譯。

現在不是很明顯(我)從NSFastEnumeration文件,但它是 在Cocoa With Love:Implementing countByEnumeratingWithState:objects:count: 的實現不必填寫所提供的對象數組解釋,但可以只設置 __enumState.itemsPtr到現有陣列(例如,一些內部存儲器)。在這種情況下,數組的內容不確定,導致崩潰。

通過

id obj = __enumState.itemsPtr[i]; 

更換

id obj = __objects[i]; 

給出了預期的結果,這是你觀察到的東西。

另一參考文獻可以在"FastEnumerationSample"示例代碼中找到:

1)使用由stackbuf提供的堆棧 基於陣列:

您實施該方法時有兩種選擇。如果你這樣做,那麼你必須尊重'len'的價值。

2)返回自己的對象數組。如果 您這樣做,則返回返回數組的全長,直到您的對象缺少 ,然後返回0.例如,鏈接數組 實現可能會按順序返回每個數組,直到您通過所有數組迭代 。

在任何一種情況下,state->itemsPtr必須是有效的 數組(非零)。 ...