2013-12-21 8 views
5

ich diese Antwort gefunden: wirdWie in Schleife intern arbeitet - Objective C - Stiftung

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

Welche präsentiert wie for in Schleife implementiert.

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

Das Problem ist, dass ich es falsch gefunden habe.

Zunächst einmal, wenn Sie die automatische Referenzzählung haben (ARC) eingeschaltet, Sie haben einen Fehler

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

Screenshot of an error

Aber selbst wenn ich ARC ausschalten ich herausgefunden, dass ich __object Array scheint seltsam zu verhalten:

Screenshot of error2

Dies ist eigentlicher Code (I MAX_STACKBUFF_SIZE angenommen 40 zu sein):

@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; 

ich EXC_BAD_ACESS bekam, wenn ich versuche, den Inhalt des __object Array zu erhalten. Ich fand auch heraus, dass wenn Sie versuchen, durch __enumState.itemsPtr iterieren, es tatsächlich funktioniert.

Können Sie mir erklären, was hier vor sich geht? Warum scheint mein __objects "geschrumpft" zu sein. Und warum enthält es nicht das gewünschte Objekt? Und warum ist dieser Fehler, wenn ARC eingeschaltet ist.

Vielen Dank im Voraus für Ihre Zeit und Mühe! (Ich habe Screenshot zum besseren Verständnis, was einen Fehler verursacht)

+0

Ich verstehe es nicht, warum nicht einfach 'for in ___' verwenden? –

+1

@ 0x7fffffff Ich versuche die Implementierung von 'for in' zu verstehen. –

+0

@bluesm Den Code in dieser Antwort nicht wörtlich nehmen. Es ist bestenfalls Pseudocode *. Es ist fast sicher nicht, wie die Ersteller des Compilers die Schleife implementiert haben. –

Antwort

3

Zunächst können starke Zeiger nicht in C-Strukturen verwendet werden, wie in den "Übergang zu ARC Release Notes" erklärt, daher das Objekt-Array deklariert werden muss als

__unsafe_unretained id __objects[MAX_STACKBUFF_SIZE]; 

wenn Sie mit ARC kompilieren.

Nun ist es nicht offensichtlich ist (für mich) aus der NSFastEnumeration Dokumentation, aber es ist in Cocoa With Love:Implementing countByEnumeratingWithState:objects:count: erklärte, dass die Umsetzung braucht den gelieferten Gegenstände Array nicht zu füllen, kann aber festgelegt nur __enumState.itemsPtr auf ein bestehendes Array (zB einig interne Speicher). In diesem Fall ist der Inhalt des Arrays __objects undefiniert, was den Absturz verursacht.

Ersetzen

id obj = __objects[i]; 

von

id obj = __enumState.itemsPtr[i]; 

gibt das erwartete Ergebnis, das ist, was Sie beobachtet.

Eine weitere Referenz kann in dem "FastEnumerationSample" Beispielcode gefunden werden:

Sie zwei Möglichkeiten, wenn zur Durchführung dieses Verfahrens:

1) die Stapel basierten Array von stackbuf bereitgestellt verwenden. Wenn Sie dies tun, müssen Sie den Wert von 'len' respektieren.

2) Geben Sie Ihr eigenes Array von Objekten zurück. Wenn Sie dies tun, geben Sie die volle Länge des zurückgegebenen Arrays zurück, bis keine Objekte mehr vorhanden sind, und geben Sie dann 0 zurück. Zum Beispiel kann eine verknüpfte Array-Implementierung jedes Array in dieser Reihenfolge zurückgeben, bis Sie über alle Arrays iterieren.

In jedem Fall muss state->itemsPtr ein gültiges Array (nicht-Null) sein. ...