для кожного циклу в 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.