Как мне перебрать NSArray?

Я смог получить время создания в posix, запустив команду stat и выведя результат.

commands.getoutput('stat FILENAME').split('\"')[7]

Вернул стат вне python из терминала (OS X):

805306374 3382786932 -rwx------ 1 km staff 0 1098083 "Aug 29 12:02:05 2013" "Aug 29 12:02:05 2013" "Aug 29 12:02:20 2013" "Aug 27 12:35:28 2013" 61440 2150 0 testfile.txt

... где четвертое datetime - это создание файла (а не время смены времени, как отмечалось в других комментариях).

441
задан Quinn Taylor 14 June 2009 в 16:35
поделиться

2 ответа

Обычно предпочтительный код для 10.5 + / iOS.

for (id object in array) {
    // do something with object
}

Эта конструкция используется для перечисления объектов в коллекции, которая соответствует протоколу NSFastEnumeration . Этот подход имеет преимущество в скорости, потому что он сохраняет указатели на несколько объектов (полученных с помощью одного вызова метода) в буфере и выполняет итерацию по ним, продвигаясь по буферу с использованием арифметики указателей. Это намного быстрее, чем вызов -objectAtIndex: каждый раз в цикле.

It ' Также стоит отметить, что хотя вы технически можете использовать цикл for-in для перехода через NSEnumerator , я обнаружил, что это сводит на нет практически все преимущества скорости быстрого перечисления. Причина в том, что реализация по умолчанию NSEnumerator -countByEnumeratingWithState: objects: count: помещает только один объект в буфер при каждом вызове.

Я сообщил об этом в радаре. : // 6296108 (Быстрое перечисление NSEnumerators происходит медленно), но оно было возвращено как Not To Be Fixed. Причина в том, что быстрое перечисление предварительно выбирает группу объектов, и если вы хотите перечислить только до заданной точки в перечислителе (например, пока не будет найден конкретный объект или не будет выполнено условие) и использовать тот же перечислитель после выхода из него петли, часто бывает так, что несколько объектов пропускаются.

Если вы пишете код для OS X 10.6 / iOS 4.0 и выше, у вас также есть возможность использовать блочные API-интерфейсы для перечисления массивов и других коллекций:

[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    // do something with object
}];

Вы также можете использовать -enumerateObjectsWithOptions: usingBlock: и передать NSEnumerationConcurrent и / или NSEnumerationReverse в качестве аргумента параметров.


10.4 или более ранняя версия

стандартная идиома для pre-10.5 - использовать NSEnumerator и цикл while, например:

NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
  // do something with object
}

Я рекомендую не усложнять. Привязка себя к типу массива негибкая, и предполагаемое увеличение скорости с помощью -objectAtIndex: в любом случае несущественно для улучшения с быстрым перечислением на 10.5+. (Быстрое перечисление фактически использует арифметику указателей в базовой структуре данных и устраняет большую часть накладных расходов на вызов методов.) Преждевременная оптимизация никогда не бывает хорошей идеей - она ​​приводит к более беспорядочному коду для решения проблемы, которая в любом случае не является вашим узким местом.

При использовании -objectEnumerator вы очень легко переходите на другую перечисляемую коллекцию (например, NSSet , ключи в NSDictionary и т. Д.) Или даже переключаетесь на -reverseObjectEnumerator для обратного перечисления массива без каких-либо других изменений кода. Если код итерации находится в методе, вы можете даже передать любой NSEnumerator , и код даже не должен заботиться о , что он повторяет. Дальше, NSEnumerator (по крайней мере, те, которые предоставлены кодом Apple) сохраняет перечисляемую им коллекцию, пока имеется больше объектов, поэтому вам не нужно беспокоиться о том, как долго будет существовать автоматически выпущенный объект.

Возможно, самая большая вещь, от которой вас защищает NSEnumerator (или быстрое перечисление), - это изменение изменяемой коллекции (массива или иного) под вами без вашего ведома , пока вы ее перечисляете. Если вы обращаетесь к объектам по индексу, вы можете столкнуться со странными исключениями или нестандартными ошибками (часто спустя долгое время после того, как возникла проблема), которые могут быть ужасными для отладки. Перечисление с использованием одной из стандартных идиом ведет себя "без сбоев", поэтому проблема (вызванная неправильным кодом) проявится сразу же, когда вы попытаетесь получить доступ к следующему объекту после того, как произошла мутация. По мере того, как программы становятся более сложными и многопоточными или даже зависят от чего-то, что может изменять сторонний код, уязвимый код перечисления становится все более проблематичным. Инкапсуляция и абстракция FTW! : -)


665
ответ дан 22 November 2019 в 23:07
поделиться

Для OS X 10.4.x и более ранних версий:

 int i;
 for (i = 0; i < [myArray count]; i++) {
   id myArrayElement = [myArray objectAtIndex:i];
   ...do something useful with myArrayElement
 }

Для OS X 10.5.x (или iPhone) и более поздних версий:

for (id myArrayElement in myArray) {
   ...do something useful with myArrayElement
}
124
ответ дан 22 November 2019 в 23:07
поделиться