Ответ 1
NSEnumerator
- это старый способ перечислить коллекции. Он включает в себя создание объекта для представления перечисления, а затем вызов метода для него для каждой отдельной итерации. Хотя это было прекрасно исправным на протяжении многих лет, оно не очень эффективно, поскольку оно включает по крайней мере одно сообщение, отправляемое на каждую итерацию цикла. NSFastEnumeration
- это более современный подход, который использует поддержку родного языка для обеспечения гораздо более эффективного перечисления. Способ, которым он работает под капотом, заключается в создании структуры, которая представляет текущее состояние перечисления и многократно вызывает -countByEnumeratingWithState:objects:count:
в коллекции. Этот метод возвращает массив массивов C в objects
out-param, а также счетчик в параметре count
out-param. Это позволяет вызывающему затем перебирать массив 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.