untuk setiap loop di Objective-C untuk mengakses kamus NSMutable

268

Saya menemukan beberapa kesulitan dalam mengakses kunci dan nilai kamus yang bisa berubah di Objective-C.

Misalkan saya punya ini:

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

Saya dapat mengatur kunci dan nilai. Sekarang, saya hanya ingin mengakses setiap kunci dan nilai, tetapi saya tidak tahu jumlah kunci yang ditetapkan.

Dalam PHP itu sangat mudah, sesuatu sebagai berikut:

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

Bagaimana mungkin di Objective-C?

Sagar R. Kothari
sumber

Jawaban:

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

Ini berfungsi untuk setiap kelas yang sesuai dengan protokol NSFastEnumeration (tersedia di 10.5+ dan iOS), meskipun NSDictionarymerupakan salah satu dari sedikit koleksi yang memungkinkan Anda menghitung kunci bukan nilai. Saya sarankan Anda membaca tentang penghitungan cepat di Topik Pemrograman Koleksi .

Oh, saya harus menambahkan bahwa Anda TIDAK PERNAH harus memodifikasi koleksi sambil menghitung melalui itu.

zneak
sumber
4
Saya bertanya-tanya, apakah seharusnya: for (NSString * key [xyz allKeys]) ?? Atau apakah itu tidak terlalu penting.
FlowUI. SimpleUITesting.com
6
@ user76859403 Menghitung kamus, pada kenyataannya, menyebutkan kunci. for (NSString* key in [xyz allKeys])secara konseptual adalah hal yang sama.
zneak
Gunakan [xyz allKeys] jika Anda perlu mematikan kamus saat menghitung kunci. Lihat jawaban saya di bawah ini.
Brody Robertson
Apakah loop ini mengembalikan urutan yang sama sepanjang waktu? Atau apakah kita perlu cara lain untuk menggunakannya untuk bagian TableView?
ymutlu
1
@ymutlu, kamus Kakao tidak berurutan. Ini berarti bahwa urutan pengulangannya dapat berubah setiap kali Anda memodifikasinya.
zneak
98

Hanya untuk tidak meninggalkan opsi 10.6+ untuk menghitung kunci dan nilai menggunakan blok ...

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

Jika Anda ingin tindakan terjadi secara bersamaan:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];
Quinn Taylor
sumber
2
3 cara berbeda untuk menghitung melalui kamus. . . heh, ini mengingatkan saya pada jawaban "Fitur Bahasa Aneh" di mana VB memiliki 7 jenis loop yang berbeda.
dreamlax
3
Yah ... objectEnumerator ditambahkan pada 1994, for (... in ...) sekitar 2006, dan Blocks ditambahkan pada 2009. Bentuk blok enumerasi adalah kejatuhan alami.
bbum
Hal ini tampaknya menjadi lebih cepat dari standar untuk ... di konstruk: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration
lkraider
1
@ lkraider, saya mengomentari posting itu, yang benar-benar membandingkan enumerasi berbasis blok dengan yang lama untuk loop, bukan untuk ... dalam membangun.
Quinn Taylor
Untuk apa ini *stop? Bagaimana Anda memanfaatkannya? Ada referensi?
borisdiakur
13

Jika Anda perlu mengubah kamus saat melakukan enumerasi:

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}
Brody Robertson
sumber
Alasannya adalah allKeysmengembalikan salinan kunci. Jadi aman untuk mematikan kamus.
Honghao Zhang
5

Cara termudah untuk menghitung kamus adalah

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

di mana tDictionaryadalah NSDictionaryatau NSMutableDictionaryAnda ingin iterate.

Avinash
sumber
2

Penghitungan cepat ditambahkan dalam 10,5 dan dalam OS iPhone, dan ini secara signifikan lebih cepat, bukan hanya gula sintaksis. Jika Anda harus menargetkan runtime yang lebih lama (yaitu 10,4 dan mundur), Anda harus menggunakan metode penghitungan lama:

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" ...
}

Anda tidak melepaskan objek enumerator, dan Anda tidak dapat mengatur ulangnya. Jika Anda ingin memulai dari awal, Anda harus meminta objek enumerator baru dari kamus.

dreamlax
sumber
1

Anda dapat menggunakan -[NSDictionary allKeys]untuk mengakses semua kunci dan memutarnya.

gcamp
sumber
2
Benar, tetapi ini memang membuat array autoreleased tambahan, yang bisa sangat boros, terutama untuk kamus dengan banyak kunci.
Quinn Taylor