для кожного циклу в Objective-C для доступу до словника NSMutable


268

У мене виникають певні труднощі з доступом до змінних ключів і значень словника в Objective-C.

Припустимо, у мене це:

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

Я можу встановити ключі та значення. Тепер я просто хочу отримати доступ до кожного ключа та значення, але я не знаю кількість встановлених ключів.

У PHP це дуже просто, щось таке:

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

Як це можливо в Objective-C?

Відповіді:


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

Це працює для кожного класу, який відповідає протоколу NSFastEnumeration (доступний для версій 10.5+ та iOS), хоча NSDictionaryце одна з небагатьох колекцій, яка дозволяє перелічувати ключі замість значень. Пропоную прочитати про швидке перерахування в Темі програмування колекцій .

О, я хочу додати, що НІКОЛИ не слід змінювати колекцію, перераховуючи її.


4
Мені було цікаво, чи не слід було це: для (ключ NSString * в [xyz allKeys]) ?? Або це насправді не має значення.
FlowUI. SimpleUITesting.com

6
@ user76859403 Перерахування словника, насправді, перераховує клавіші. for (NSString* key in [xyz allKeys])концептуально те саме.
zneak

Використовуйте [xyz allKeys], якщо вам потрібно вимкнути словник під час перерахування клавіш. Дивіться мою відповідь нижче.
Броді Робертсон

Чи ця петля повертає той самий порядок весь час? Або нам потрібен інший спосіб використовувати його для розділів TableView?
ymutlu

1
@ymutlu, словники какао не упорядковані. Це означає, що порядок їх повторення може змінюватися кожного разу, коли ви їх змінюєте.
zneak

98

Тільки щоб не пропустити варіант 10.6+ для перерахування ключів та значень за допомогою блоків ...

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

Якщо ви хочете, щоб дії відбувалися одночасно:

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

2
3 різні способи перерахування через словник. . . Гей, це нагадує мені відповідь "Найстрашніша мовна особливість", де VB має 7 різних циклів.
dreamlax

3
Ну ... objectEnumerator був доданий в 1994 році, для (... в ...) приблизно в 2006 році, а Блоки були додані в 2009 році. Блокова форма перерахування - це природний випадок.
bbum

Здається, це швидше, ніж стандарт для ... у конструкції: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration
lkraider

1
@lkraider, я прокоментував цю публікацію, яка насправді порівнює блокове перерахування зі старим для циклу, а не з ... у конструкції.
Квінн Тейлор

Для чого це *stop? Як ви користуєтесь ним? Будь-яка довідка?
borisdiakur

13

Якщо вам потрібно вимкнути словник під час перерахування:

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}

Причина - allKeysповернення копії ключів. Тож безпечно мутувати словник.
Honghao Zhang

5

Найпростіший спосіб перерахувати словник - це

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

де tDictionaryє NSDictionaryабо NSMutableDictionaryви хочете повторити.


4

Я пропоную вам прочитати « Перерахування: проходження елементів колекції» частини Посібника з програмування колекцій для какао . Існує зразок коду для ваших потреб.


Це хороші посилання, хоча код @zneak розміщений набагато простіше і швидше, якщо ви можете побудувати для 10.5+ або iPhone.
Квінн Тейлор

2

Швидке перерахування було додано в 10,5 та в ОС iPhone, і це значно швидше, а не лише синтаксичний цукор. Якщо вам потрібно націлити на старіший час виконання (тобто 10.4 і назад), вам доведеться використовувати старий метод перерахування:

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

Ви не відпускаєте об'єкт перелічувача і не можете його скинути. Якщо ви хочете почати заново, вам потрібно попросити новий словник з об’єкту.


1

Ви можете використовувати -[NSDictionary allKeys]для доступу до всіх клавіш і прокручувати їх.


2
Щоправда, але це створює додатковий автоматичний випуск масиву, який може бути досить марнотратним, особливо для словників з великою кількістю клавіш.
Квінн Тейлор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.