Какао NSArray / NSSet: -makeObjectsPerformSelector: против быстрого перечисления - PullRequest
14 голосов
/ 24 февраля 2009

Я хочу выполнить одно и то же действие над несколькими объектами, хранящимися в NSSet.

Моя первая попытка использовала быстрое перечисление:

for (id item in mySetOfObjects)
    [item action];

, который работает довольно хорошо. Тогда я подумал:

[mySetOfObjects makeObjectsPerformSelector:@selector(action)];

А теперь я не знаю, какой лучший выбор. Насколько я понимаю, два решения эквивалентны. Но есть ли аргументы для предпочтения одного решения другому?

Ответы [ 5 ]

22 голосов
/ 24 февраля 2009

Я бы поспорил с использованием makeObjectsPerformSelector, поскольку он позволяет объекту NSSet позаботиться о своей собственной индексации, циклической обработке и диспетчеризации сообщений. Люди, написавшие код NSSet, скорее всего, знают, как лучше всего реализовать этот конкретный цикл.

В худшем случае они просто реализуют точно такой же цикл, и все, что вы получите, это немного более чистый код (нет необходимости в замкнутом цикле). В лучшем случае они внесли некоторую внутреннюю оптимизацию, и код на самом деле будет работать быстрее.

Эта тема кратко упоминается в документе Apple Performance Speed ​​, в разделе «Развертывание циклов».

Если вы беспокоитесь о производительности, лучше всего настроить быструю программу, которая выполняет некоторые селекторы для объектов в наборе. Запустите его несколько миллионов раз и определите разницу между двумя разными случаями.

7 голосов
/ 11 марта 2011

Мне тоже был задан этот вопрос. Я нахожу в документации Apple "Темы программирования коллекций" в разделе " Sets: неупорядоченные коллекции объектов " следующее:

Метод NSSet objectEnumerator позволяет вы пересекаете элементы заданного одним. А также themakeObjectsPerformSelector: и makeObjectsPerformSelector: withObject: методы обеспечивают отправку сообщений на отдельные объекты в наборе. В в большинстве случаев быстрое перечисление должно быть используется, потому что это быстрее и больше гибкий, чем использование NSEnumerator или makeObjectsPerformSelector: метод. Подробнее о перечислении см. «Перечисление: пересечение Элементы коллекции. ”

Это наводит меня на мысль, что быстрое перечисление все еще является наиболее эффективным средством для этого приложения.

4 голосов
/ 27 февраля 2009

Я бы не использовал makeObjectsPerformSelector по той простой причине, что это тот тип вызова, который вы не видите все так часто. Вот почему, например, мне нужно добавить код отладки, поскольку массив перечисляется, и вы действительно не сможете сделать это с помощью makeObjectsPerformSelector, если вы не измените работу кода в режиме Release, что на самом деле нет нет.

for (id item in mySetOfObjects)
{
    #if MY_DEBUG_BUILD
    if ([item isAllMessedUp])
        NSLog(@"we found that wily bug that has been haunting us"); 
    #endif

    [item action];
}

- Том

2 голосов
/ 24 февраля 2009

makeObjectsPerformSelector: может быть немного быстрее, но я сомневаюсь, что будет практическая разница в 99% случаев. Это немного более кратко и читабельно, хотя, я бы использовал его по этой причине.

1 голос
/ 14 августа 2012

Если единственной проблемой является чистая скорость (т. Е. Вы создаете какой-то движок рендеринга, в котором учитывается каждый крошечный цикл ЦП), то самым быстрым из всех возможных вариантов NSCollection (с iOS 5.0 ~ 6.0) является различный способ. методы "enumerateObjectsUsingBlock". Я понятия не имею, почему это так, но я проверил это, и, похоже, это так ...

Я написал небольшой тест для создания коллекций из сотен тысяч объектов, каждый из которых имеет метод, который суммирует простой массив целых чисел. Каждая из этих коллекций была вынуждена выполнять различные типы итераций (для цикла, быстрого перечисления, makeObjectsPerformSelector и enumerateObjectsUsingBlock) миллионы раз, и почти во всех случаях методы enumerateObjectsUsingBlock легко выигрывали в ходе испытаний. *

Единственный раз, когда это не было правдой, это когда память начала заполняться (когда я начал запускать ее с миллионами объектов), после чего она начала проигрывать "makeObjectsPerformSelector".

Извините, я не сделал снимок кода, но это очень простой тест, я настоятельно рекомендую попробовать и убедиться в этом сам. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...