для каждого цикла в 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
Мне было интересно, не так ли: for (ключ 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 разных способа перечисления через словарь. , , хех, это напоминает мне ответ "Strangest Language Feature", где VB имеет 7 различных типов циклов.
Dreamlax

3
Что ж ... objectEnumerator был добавлен в 1994 году, for (... in ...) примерно в 2006 году, а блоки были добавлены в 2009 году. Блочная форма перечисления - это естественные последствия.
bbum

Кажется, это быстрее, чем стандарт для ... в конструкции: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration
lkraider

1
@lkraider, я прокомментировал этот пост, который фактически сравнивает основанное на блоках перечисление со старым циклом for, а не for ... в конструкции.
Куинн Тейлор

Для чего *stop? Как вы используете это? Любая ссылка?
Борисдиакур

13

Если вам нужно изменить словарь при перечислении:

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

Причина в том, что allKeysвозвращает копию ключей. Так что безопасно мутировать словарь.
Хунхао Чжан

5

Самый простой способ перечислить словарь

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

где tDictionaryнаходится NSDictionaryили NSMutableDictionaryвы хотите повторить.


5

Я предлагаю вам прочитать перечисление: пересекающее на элементы коллекции часть коллекций Руководства по программированию на какао . Существует пример кода для ваших нужд.


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

2

Быстрое перечисление было добавлено в 10.5 и в iPhone OS, и это значительно быстрее, а не только синтаксический сахар. Если вам нужно ориентироваться на более раннюю среду выполнения (то есть 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.