NSEnumerator
- это старый способ перечисления по коллекциям.Он включает создание объекта для представления перечисления, а затем вызов метода для каждой отдельной итерации.Несмотря на то, что это было совершенно исправно в течение многих лет, оно не очень эффективно, так как включает в себя по крайней мере одну отправку сообщения для каждой итерации цикла.NSFastEnumeration
- более современный подход, который использует поддержку родного языка для обеспечения гораздо более эффективного перечисления.Он работает под капотом, создавая структуру, которая представляет текущее состояние перечисления, и неоднократно вызывает -countByEnumeratingWithState:objects:count:
в коллекции.Этот метод возвращает массив объектов C в выходном параметре objects
, а также счетчик в выходном параметре count
.Это позволяет вызывающей стороне затем перебирать массив C.По сути, это означает, что один вызов сообщения на кусок объектов, который, в зависимости от коллекции, может быть столь же эффективным, как один вызов сообщения для получения всех объектов.
Если у вас есть немного кода, который выглядит как
for (id obj in myArray) {
[obj doSomething];
}
Это преобразуется компилятором в нечто, примерно эквивалентное
NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
for (NSUInteger i = 0; i < __count; i++) {
id obj = __objects[i];
[obj doSomething];
}
}
Фактические используемые переменные скрыты, и максимальный размер буфера объекта также зависит от реализации,но основная идея есть.Он переводит итерацию по коллекции obj-c в итерацию по массиву C.