für jede Schleife in Objective-C für den Zugriff auf das NSMutable-Wörterbuch

268

Ich habe einige Schwierigkeiten beim Zugriff auf veränderbare Wörterbuchschlüssel und -werte in Objective-C.

Angenommen, ich habe Folgendes:

NSMutableDictionary *xyz=[[NSMutableDictionary alloc] init];

Ich kann Schlüssel und Werte einstellen. Jetzt möchte ich nur auf jeden Schlüssel und Wert zugreifen, aber ich kenne die Anzahl der eingestellten Schlüssel nicht.

In PHP ist es sehr einfach, etwas wie folgt:

foreach ($xyz as $key => $value)

Wie ist es in Objective-C möglich?

Sagar R. Kothari
quelle

Antworten:

662
for (NSString* key in xyz) {
    id value = xyz[key];
    // do stuff
}

Dies funktioniert für jede Klasse, die dem NSFastEnumeration-Protokoll (verfügbar ab 10.5 und iOS) entspricht, NSDictionaryist jedoch eine der wenigen Sammlungen, mit denen Sie Schlüssel anstelle von Werten auflisten können. Ich schlage vor, Sie lesen etwas über die schnelle Aufzählung im Thema Programmierung von Sammlungen .

Oh, ich sollte jedoch hinzufügen, dass Sie NIEMALS eine Sammlung ändern sollten, während Sie sie aufzählen.

zneak
quelle
4
Ich habe mich gefragt, hätte es nicht sein sollen: für (NSString * tippe [xyz allKeys] ein) ?? Oder spielt es keine Rolle?
FlowUI. SimpleUITesting.com
6
@ user76859403 Beim Auflisten eines Wörterbuchs werden die Schlüssel aufgelistet. for (NSString* key in [xyz allKeys])ist konzeptionell das gleiche.
Zneak
Verwenden Sie [xyz allKeys], wenn Sie das Wörterbuch während der Aufzählung der Schlüssel mutieren müssen. Siehe meine Antwort unten.
Brody Robertson
Gibt diese Schleife immer die gleiche Reihenfolge zurück? Oder brauchen wir eine andere Möglichkeit, es für TableView-Abschnitte zu verwenden?
Ymutlu
1
@ymutlu, Kakaowörterbücher sind ungeordnet. Dies bedeutet, dass sich die Reihenfolge, in der sie iterieren, ändern kann, wenn Sie sie ändern.
Zneak
98

Nur um die Option 10.6+ zum Aufzählen von Schlüsseln und Werten mithilfe von Blöcken nicht auszulassen ...

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

Wenn Sie möchten, dass die Aktionen gleichzeitig ausgeführt werden:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];
Quinn Taylor
quelle
2
3 verschiedene Möglichkeiten, ein Wörterbuch aufzulisten. . . heh, das erinnert mich an die Antwort "Strangest Language Feature", bei der VB 7 verschiedene Arten von Schleifen hat.
Dreamlax
3
Nun ... objectEnumerator wurde 1994 hinzugefügt, der for (... in ...) ungefähr 2006 und Blocks wurden 2009 hinzugefügt. Die Blockform der Aufzählung ist ein natürlicher Fallout.
bbum
Dies scheint schneller zu sein als der Standard für ... im Konstrukt: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration
lkraider
1
@lkraider, ich habe diesen Beitrag kommentiert, der die blockbasierte Aufzählung tatsächlich mit einer alten for-Schleife vergleicht, nicht mit der for ... im Konstrukt.
Quinn Taylor
Wofür ist das *stop? Wie nutzt du es? Irgendeine Referenz?
Borisdiakur
13

Wenn Sie das Wörterbuch während der Aufzählung mutieren müssen :

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}
Brody Robertson
quelle
Der Grund ist, dass allKeyseine Kopie der Schlüssel zurückgegeben wird. Es ist also sicher, das Wörterbuch zu mutieren.
Honghao Zhang
5

Der einfachste Weg, ein Wörterbuch aufzulisten, ist

for (NSString *key in tDictionary.keyEnumerator) 
{
    //do something here;
}

wo tDictionaryist das NSDictionaryoder NSMutableDictionarydu willst iterieren.

Avinash
quelle
2

In 10.5 und im iPhone OS wurde eine schnelle Aufzählung hinzugefügt, die nicht nur syntaktischen Zucker, sondern auch erheblich schneller ist. Wenn Sie auf die ältere Laufzeit (z. B. 10.4 und zurück) abzielen müssen, müssen Sie die alte Aufzählungsmethode verwenden:

NSDictionary *myDict = ... some keys and values ...
NSEnumerator *keyEnum = [myDict keyEnumerator];
id key;

while ((key = [keyEnum nextObject]))
{
    id value = [myDict objectForKey:key];
    ... do work with "value" ...
}

Sie geben das Enumerator-Objekt nicht frei und können es nicht zurücksetzen. Wenn Sie von vorne beginnen möchten, müssen Sie ein neues Enumerator-Objekt aus dem Wörterbuch anfordern.

Dreamlax
quelle
1

Sie können -[NSDictionary allKeys]damit auf alle Schlüssel zugreifen und diese durchlaufen.

gcamp
quelle
2
Stimmt, aber dies erzeugt ein zusätzliches autorelease-Array, was ziemlich verschwenderisch sein kann, insbesondere für Wörterbücher mit vielen Schlüsseln.
Quinn Taylor