Значения и наборы

Несмотря на то, что Objective C является языком объектно-ориентированного программирования, это - надмножество C, что означает, что можно использовать любой стандарт C скалярные (необъектные) типы как int, float и char в коде Objective C. Существуют также дополнительные скалярные типы, доступные в Сенсорных приложениях Какао и Какао, такой как NSInteger, NSUInteger и CGFloat, которые имеют различные определения в зависимости от целевой архитектуры.

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

Возможно объявить массив C-стиля в Objective C, но Вы найдете, что наборы в Сенсорных приложениях Какао и Какао обычно представляются с помощью экземпляров классов как NSArray или NSDictionary. Эти классы могут только использоваться для сбора объектов Objective C, что означает, что необходимо будет создать экземпляры классов как NSValue, NSNumber или NSString для представления значений, прежде чем можно будет добавить их к набору.

Предыдущие главы в этом руководстве делают частое использование NSString класс и его инициализация и методы фабрики классов, а также Objective C @"string" литерал, предлагающий краткий синтаксис для создания NSString экземпляр. Эта глава объясняет, как создать NSValue и NSNumber объекты, с помощью или вызовов метода или через Objective C оценивают литеральный синтаксис.

Основные типы примитивов C доступны в Objective C

Каждый стандарт C скалярные типы переменных доступен в Objective C:

    int someInteger = 42;
    float someFloatingPointNumber = 3.1415;
    double someDoublePrecisionFloatingPointNumber = 6.02214199e23;

а также стандарт C операторы:

    int someInteger = 42;
    someInteger++;            // someInteger == 43
 
    int anotherInteger = 64;
    anotherInteger--;         // anotherInteger == 63
 
    anotherInteger *= 2;      // anotherInteger == 126

Если Вы используете скалярный тип для свойства Objective-C, как это:

@interface XYZCalculator : NSObject
@property double currentValue;
@end

также возможно использовать операторов C на свойстве при доступе к значению через точечный синтаксис, как это:

@implementation XYZCalculator
- (void)increment {
    self.currentValue++;
}
- (void)decrement {
    self.currentValue--;
}
- (void)multiplyBy:(double)factor {
    self.currentValue *= factor;
}
@end

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

Objective C определяет дополнительные типы примитивов

BOOL скалярный тип определяется в Objective C для содержания булева значения, которое является также YES или NO. Поскольку Вы могли бы ожидать, YES логически эквивалентно true и 1, в то время как NO эквивалентно false и 0.

Много параметров к методам на Сенсорных объектах Какао и Какао также используют специальные скалярные числовые типы, такой как NSInteger или CGFloat.

Например, NSTableViewDataSource и UITableViewDataSource протоколы (описанный в предыдущей главе) у обоих есть методы, запрашивающие число строк вывести на экран:

@protocol NSTableViewDataSource <NSObject>
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView;
...
@end

Эти типы, как NSInteger и NSUInteger, определяются по-другому в зависимости от целевой архитектуры. При создании для 32-разрядной среды (такой что касается iOS), они - 32-разрядные целые числа со знаком и целые без знака соответственно; при создании для 64-разрядной среды (такой что касается современного времени выполнения OS X) они - 64-разрядные целые числа со знаком и целые без знака соответственно.

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

Для локальных переменных, таких как счетчик в цикле, хорошо использовать основные типы C, если Вы знаете, что значение в стандартных пределах.

C структуры может содержать примитивные значения

Некоторое Касание Какао и Какао API использует структуры C для содержания их значений. Как пример, возможно попросить у строкового объекта диапазона подстроки, как это:

    NSString *mainString = @"This is a long string";
    NSRange substringRange = [mainString rangeOfString:@"long"];

NSRange структура содержит расположение и длину. В этом случае, substringRange будет содержать диапазон {10,4}— “l” в начале @"long" символ в основанном на нуле индексе 10 в mainString, и @"long" 4 символы в длине.

Точно так же, если необходимо записать пользовательский код для прорисовки, необходимо будет взаимодействовать с Кварцем, требующим структур, базируемых вокруг CGFloat тип данных, как NSPoint и NSSize на OS X и CGPoint и CGSize на iOS. Снова, CGFloat определяется по-другому в зависимости от целевой архитектуры.

Для получения дополнительной информации о Кварце 2D механизм получения посмотрите Кварц 2D Руководство по программированию.

Объекты могут представлять примитивные значения

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

Строки представлены экземплярами класса NSString

Поскольку Вы видели в предыдущих главах, NSString используется для представления строки символов, как Hello World. Существуют различные способы создать NSString объекты, включая стандартное выделение и инициализацию, методы фабрики классов или литеральный синтаксис:

    NSString *firstString = [[NSString alloc] initWithCString:"Hello World!"
                                                     encoding:NSUTF8StringEncoding];
    NSString *secondString = [NSString stringWithCString:"Hello World!"
                                                encoding:NSUTF8StringEncoding];
    NSString *thirdString = @"Hello World!";

Каждый из этих примеров эффективно выполняет ту же вещь — создание строкового объекта, представляющего предоставленные символы.

Основное NSString класс является неизменным, что означает, что его содержание установлено при создании и не может позже быть изменено. Если необходимо представлять различную строку, необходимо создать новый строковый объект, как это:

    NSString *name = @"John";
    name = [name stringByAppendingString:@"ny"];    // returns a new string object

NSMutableString класс является непостоянным подклассом NSString, и позволяет Вам изменять его символьное содержание во время выполнения с помощью методов как appendString: или appendFormat:, как это:

    NSMutableString *name = [NSMutableString stringWithString:@"John"];
    [name appendString:@"ny"];   // same object, but now represents "Johnny"

Строки формата используются для создания строк из других объектов или значений

Если необходимо создать строку, содержащую значения переменных, необходимо работать со строкой формата. Это позволяет Вам использовать спецификаторы формата, чтобы указать, как вставляются значения:

    int magicNumber = ...
    NSString *magicString = [NSString stringWithFormat:@"The magic number is %i", magicNumber];

Спецификаторы доступного формата описаны в Спецификаторах Формата строки. Для получения дополнительной информации о строках в целом, см. Строковое Руководство по программированию.

Числа представлены экземплярами класса NSNumber

NSNumber класс используется для представления любого из основных скалярных типов C, включая char, double, float, int, long, short, и unsigned варианты каждого, а также тип булевской переменной Objective C, BOOL.

Как с NSString, у Вас есть множество опций создать NSNumber экземпляры, включая выделение и инициализацию или методы фабрики классов:

    NSNumber *magicNumber = [[NSNumber alloc] initWithInt:42];
    NSNumber *unsignedNumber = [[NSNumber alloc] initWithUnsignedInt:42u];
    NSNumber *longNumber = [[NSNumber alloc] initWithLong:42l];
 
    NSNumber *boolNumber = [[NSNumber alloc] initWithBOOL:YES];
 
    NSNumber *simpleFloat = [NSNumber numberWithFloat:3.14f];
    NSNumber *betterDouble = [NSNumber numberWithDouble:3.1415926535];
 
    NSNumber *someChar = [NSNumber numberWithChar:'T'];

Также возможно создать NSNumber экземпляры с помощью синтаксиса литерала Objective C:

    NSNumber *magicNumber = @42;
    NSNumber *unsignedNumber = @42u;
    NSNumber *longNumber = @42l;
 
    NSNumber *boolNumber = @YES;
 
    NSNumber *simpleFloat = @3.14f;
    NSNumber *betterDouble = @3.1415926535;
 
    NSNumber *someChar = @'T';

Эти примеры эквивалентны использованию NSNumber методы фабрики классов.

Как только Вы создали NSNumber экземпляр возможно запросить скалярное значение с помощью одного из методов доступа:

    int scalarMagic = [magicNumber intValue];
    unsigned int scalarUnsigned = [unsignedNumber unsignedIntValue];
    long scalarLong = [longNumber longValue];
 
    BOOL scalarBool = [boolNumber boolValue];
 
    float scalarSimpleFloat = [simpleFloat floatValue];
    double scalarBetterDouble = [betterDouble doubleValue];
 
    char scalarChar = [someChar charValue];

NSNumber класс также предлагает методы для работы с дополнительными типами примитивов Objective C. Если необходимо создать объектное представление скаляра NSInteger и NSUInteger типы, например, удостоверяются, что Вы используете корректные методы:

    NSInteger anInteger = 64;
    NSUInteger anUnsignedInteger = 100;
 
    NSNumber *firstInteger = [[NSNumber alloc] initWithInteger:anInteger];
    NSNumber *secondInteger = [NSNumber numberWithUnsignedInteger:anUnsignedInteger];
 
    NSInteger integerCheck = [firstInteger integerValue];
    NSUInteger unsignedCheck = [secondInteger unsignedIntegerValue];

Все NSNumber экземпляры являются неизменными, и нет никакого непостоянного подкласса; при необходимости в различном числе просто используйте другого NSNumber экземпляр.

Представляйте другие значения Используя экземпляры класса NSValue

NSNumber класс является самостоятельно подклассом основного NSValue класс, обеспечивающий объектную обертку вокруг единственного значения или элемента данных. В дополнение к основным скалярным типам C, NSValue может также использоваться для представления указателей и структур.

NSValue класс предлагает различные методы фабрики создать ценность с данной стандартной структурой, упрощающей создавать экземпляр для представления, например, NSRange, как пример от ранее в главе:

    NSString *mainString = @"This is a long string";
    NSRange substringRange = [mainString rangeOfString:@"long"];
    NSValue *rangeValue = [NSValue valueWithRange:substringRange];

Также возможно создать NSValue объекты представлять пользовательские структуры. Если у Вас есть определенная потребность использовать структуру C (а не объект Objective C), чтобы хранить информацию, как это:

typedef struct {
    int i;
    float f;
} MyIntegerFloatStruct;

можно создать NSValue экземпляр путем обеспечения указателя на структуру, а также закодированный тип Objective C. @encode() директива компилятора используется для создания корректного типа Objective C, как это:

    struct MyIntegerFloatStruct aStruct;
    aStruct.i = 42;
    aStruct.f = 3.14;
 
    NSValue *structValue = [NSValue value:&aStruct
                             withObjCType:@encode(MyIntegerFloatStruct)];

Стандарт C ссылочный оператор (&) используется для обеспечения адреса aStruct для value параметр.

Большинство наборов является объектами

Несмотря на то, что возможно использовать массив C для содержания набора скалярных значений или даже объектных указателей, большинство наборов в коде Objective C является экземплярами одного из Сенсорных классов набора Какао и Какао, как NSArray, NSSet и NSDictionary.

Эти классы используются для управления группами объектов, что означает любой элемент, который Вы хотите добавить к набору, должен быть экземпляр класса Objective C. Если необходимо добавить скалярное значение, необходимо сначала создать подходящее NSNumber или NSValue экземпляр для представления его.

Вместо того, чтобы так или иначе поддерживать отдельную копию каждого собранного объекта, классы набора используют сильные ссылки для отслеживания их содержание. Это означает, что любой объект, который Вы добавляете к набору, будет поддержан, по крайней мере, пока набор поддерживается, как описано в Управляют Графом объектов через Владение и Ответственность.

В дополнение к отслеживанию их содержания каждый из Сенсорных классов набора Какао и Какао упрощает выполнять определенные задачи, такие как перечисление, получая доступ к конкретным изделиям, или узнавая, является ли определенный объект частью набора.

Основное NSArray, NSSet и NSDictionary классы являются неизменными, что означает, что их содержание установлено при создании. У каждого также есть непостоянный подкласс, чтобы позволить Вам добавлять или удалять объекты по желанию.

Для получения дополнительной информации о различных классах набора, доступных в Касании Какао и Какао, посмотрите, что Наборы Программируют Темы.

Массивам упорядочивают наборы

NSArray используется для представления упорядоченного набора объектов. Единственное требование - то, что каждый элемент является объектом Objective C — нет никакого требования для каждого объекта быть экземпляром того же класса.

Для поддержания порядка в массиве каждый элемент сохранен в основанном на нуле индексе, как показано на рисунке 6-1.

Рисунок 6-1  массив объектов Objective C

Создание массивов

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

Существует множество различной инициализации и методов фабрики, доступных, в зависимости от числа объектов:

+ (id)arrayWithObject:(id)anObject;
+ (id)arrayWithObjects:(id)firstObject, ...;
- (id)initWithObjects:(id)firstObject, ...;

arrayWithObjects: и initWithObjects: методы оба берут завершенное нолем, переменное число параметров, что означает, что необходимо включать nil как последнее значение, как это:

    NSArray *someArray =
  [NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];

Этот пример создает массив как один показанный ранее на рисунке 6-1. Первый объект, someObject, будет иметь индекс массива 0; последний объект, someValue, будет иметь индекс 3.

Если одно из предоставленных значений, возможно усечь список элементов непреднамеренно nil, как это:

    id firstObject = @"someString";
    id secondObject = nil;
    id thirdObject = @"anotherString";
    NSArray *someArray =
  [NSArray arrayWithObjects:firstObject, secondObject, thirdObject, nil];

В этом случае, someArray будет содержать только firstObject, потому что nil secondObject был бы интерпретирован как конец списка элементов.

Литеральный синтаксис

Также возможно создать массив с помощью литерала Objective C, как это:

    NSArray *someArray = @[firstObject, secondObject, thirdObject];

Вы не должны завершать список объектов с nil при использовании этого литерального синтаксиса, и фактически nil недопустимое значение. При попытке выполнить следующий код, например, Вы получите исключение во время выполнения:

    id firstObject = @"someString";
    id secondObject = nil;
    NSArray *someArray = @[firstObject, secondObject];
    // exception: "attempt to insert nil object"

Если действительно необходимо представлять a nil значение в одном из классов набора, необходимо использовать NSNull singleton-класс, как описано в Представляют ноль с NSNull.

Запросы объектов массива

Как только Вы создали массив, можно запросить его для получения информации как число объектов, или содержит ли он данный элемент:

    NSUInteger numberOfItems = [someArray count];
 
    if ([someArray containsObject:someString]) {
        ...
    }

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

    if ([someArray count] > 0) {
        NSLog(@"First item is: %@", [someArray objectAtIndex:0]);
    }

Этот пример проверяет, больше ли число элементов, чем нуль. Если так, это регистрирует описание первого элемента, имеющего индекс нуля.

Преобразование в нижний индекс

Существует также нижняя альтернатива синтаксиса использованию objectAtIndex:, который точно так же, как получает доступ к значению в стандарте C массив. Предыдущий пример мог быть переписан как это:

    if ([someArray count] > 0) {
        NSLog(@"First item is: %@", someArray[0]);
    }

Сортировка объектов массива

NSArray класс также предлагает множество методов для сортировки его собранных объектов. Поскольку NSArray является неизменным, каждый из этих методов возвращает новый массив, содержащий элементы в сортированном порядке.

Как пример, можно сортировать массив строк результатом вызова compare: на каждой строке, как это:

    NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
    NSArray *sortedStrings =
                 [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

Переменчивость

Несмотря на то, что NSArray сам класс является неизменным, это не имеет никакого влияния ни на какие собранные объекты. Если Вы добавляете непостоянную строку к неизменному массиву, например, как это:

NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
NSArray *immutableArray = @[mutableString];

нет ничего, чтобы мешать Вам видоизменить строку:

    if ([immutableArray count] > 0) {
        id string = immutableArray[0];
        if ([string isKindOfClass:[NSMutableString class]]) {
            [string appendString:@" World!"];
        }
    }

Если необходимо быть в состоянии добавить или удалить объекты из массива после начального создания, необходимо будет использовать NSMutableArray, который добавляет множество методов, чтобы добавить, удалить или заменить один или несколько объектов:

    NSMutableArray *mutableArray = [NSMutableArray array];
    [mutableArray addObject:@"gamma"];
    [mutableArray addObject:@"alpha"];
    [mutableArray addObject:@"beta"];
 
    [mutableArray replaceObjectAtIndex:0 withObject:@"epsilon"];

Этот пример создает массив, заканчивающийся с объектами @"epsilon", @"alpha", @"beta".

Также возможно сортировать непостоянный массив на месте, не создавая вторичный массив:

    [mutableArray sortUsingSelector:@selector(caseInsensitiveCompare:)];

В этом случае содержавшие элементы будут сортированы в возрастание, нечувствительный к регистру порядок @"alpha", @"beta", @"epsilon".

Наборам не упорядочивают наборы

NSSet подобно массиву, но поддерживает неупорядоченную группу отдельных объектов, как показано на рисунке 6-2.

Рисунок 6-2  ряд объектов

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

Основное NSSet класс является снова неизменным, таким образом, его содержание должно быть указано при создании, с помощью или выделения и инициализации или метода фабрики классов, как это:

    NSSet *simpleSet =
      [NSSet setWithObjects:@"Hello, World!", @42, aValue, anObject, nil];

Как с NSArray, initWithObjects: и setWithObjects: методы оба берут завершенное нолем, переменное число параметров. Непостоянное NSSet подкласс NSMutableSet.

Даже при попытке добавить объект несколько раз, наборы только хранят одну ссылку на отдельный объект:

    NSNumber *number = @42;
    NSSet *numberSet =
      [NSSet setWithObjects:number, number, number, number, nil];
    // numberSet only contains one object

Для получения дополнительной информации о наборах посмотрите Наборы: неупорядоченные Наборы Объектов.

Словари собирают пары ключ/значение

Вместо того, чтобы просто поддерживать упорядоченный или неупорядоченный набор объектов, NSDictionary хранит объекты против данных ключей, которые могут тогда использоваться для извлечения.

Это - наиболее успешная практика для использования строковых объектов в качестве ключей словаря, как показано на рисунке 6-3.

Рисунок 6-3  словарь объектов

Создание словарей

Можно создать словари с помощью или выделения и инициализации или методов фабрики классов, как это:

    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                   someObject, @"anObject",
             @"Hello, World!", @"helloString",
                          @42, @"magicNumber",
                    someValue, @"aValue",
                             nil];

Обратите внимание на то, что для dictionaryWithObjectsAndKeys: и initWithObjectsAndKeys: методы, каждый объект указан перед его ключом, и снова, должен быть завершен нолем список объектов и ключей.

Литеральный синтаксис

Objective C также предлагает литеральный синтаксис для создания словаря, как это:

    NSDictionary *dictionary = @{
                  @"anObject" : someObject,
               @"helloString" : @"Hello, World!",
               @"magicNumber" : @42,
                    @"aValue" : someValue
    };

Обратите внимание на то, что для литералов словаря, ключ указан перед его объектом и не завершается нолем.

Запросы словарей

Как только Вы создали словарь, можно попросить у него объекта, хранившего против данного ключа, как это:

    NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];

Если объект не найден, objectForKey: метод возвратится nil.

Существует также нижняя альтернатива синтаксиса использованию objectForKey:, который похож на это:

    NSNumber *storedNumber = dictionary[@"magicNumber"];

Переменчивость

Если необходимо добавить или удалить объекты из словаря после создания, необходимо использовать NSMutableDictionary подкласс, как это:

    [dictionary setObject:@"another string" forKey:@"secondString"];
    [dictionary removeObjectForKey:@"anObject"];

Представляйте ноль с NSNull

Не возможно добавить nil к классам набора, описанным в этом разделе, потому что nil в Objective C не означает “объекта”. Если Вы не должны представлять “объект” в наборе, можно использовать NSNull класс:

    NSArray *array = @[ @"string", @42, [NSNull null] ];

NSNull singleton-класс, что означает что null метод будет всегда возвращать тот же экземпляр. Это означает, что можно проверить, равен ли объект в массиве совместно используемому NSNull экземпляр:

    for (id object in array) {
        if (object == [NSNull null]) {
            NSLog(@"Found a null object");
        }
    }

Используйте наборы для сохранения графа объектов

NSArray и NSDictionary классы упрощают писать свое содержание непосредственно в диск, как это:

    NSURL *fileURL = ...
    NSArray *array = @[@"first", @"second", @"third"];
 
    BOOL success = [array writeToURL:fileURL atomically:YES];
    if (!success) {
        // an error occured...
    }

Если каждый содержащий в нем объект является одним из типов списка свойств (NSArray, NSDictionary, NSString, NSData, NSDate и NSNumber), возможно воссоздать всю иерархию от диска, как это:

    NSURL *fileURL = ...
    NSArray *array = [NSArray arrayWithContentsOfURL:fileURL];
    if (!array) {
        // an error occurred...
    }

Для получения дополнительной информации о списках свойств см. Руководство по программированию Списка свойств.

Если необходимо сохранить другие типы объектов, чем просто стандартные классы списка свойств, показанные выше, можно использовать объект archiver, такой как NSKeyedArchiver, создать архив собранных объектов.

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

NSArray, NSSet и NSDictionary классы, и их непостоянные подклассы, вся поддержка NSCoding, что означает, что можно сохранить сложные иерархии объектов с помощью archiver. При использовании Интерфейсного Разработчика для разметки окон и представлений, например, получающийся файл пера является просто архивом иерархии объектов, которую Вы создали визуально. Во время выполнения файл пера разархивирован к иерархии объектов с помощью соответствующих классов.

Для получения дополнительной информации об Архивах см. Руководство по программированию Архивов и Сериализации.

Используйте самые эффективные методы перечисления набора

Objective C и Касание Какао или Какао предлагают множество способов перечислить содержание набора. Несмотря на то, что возможно использовать традиционный C for цикл для итерации по содержанию, как это:

    int count = [array count];
    for (int index = 0; index < count; index++) {
        id eachObject = [array objectAtIndex:index];
        ...
    }

это - наиболее успешная практика для использования одного из других методов, описанных в этом разделе.

Быстрое перечисление упрощает перечислять набор

Много классов набора соответствуют NSFastEnumeration протокол, включая NSArray, NSSet и NSDictionary. Это означает, что можно использовать быстрое перечисление, функцию уровня языка Objective C.

Быстрый синтаксис перечисления, чтобы перечислить содержание массива или установить похож на это:

    for (<Type> <variable> in <collection>) {
        ...
    }

Как пример, Вы могли бы использовать быстрое перечисление для журналирования описания каждого объекта в массиве, как это:

    for (id eachObject in array) {
        NSLog(@"Object: %@", eachObject);
    }

eachObject переменная установлена автоматически в текущий объект для каждого, проходят через цикл, таким образом, один оператор журнала появляется на объект.

При использовании быстрого перечисления со словарем Вы выполняете итерации по ключам словаря, как это:

    for (NSString *eachKey in dictionary) {
        id object = dictionary[eachKey];
        NSLog(@"Object: %@ for key: %@", object, eachKey);
    }

Быстрое перечисление ведет себя во многом как стандарт C for цикл, таким образом, можно использовать break ключевое слово для прерывания итерации, или continue совершенствоваться к следующему элементу.

При перечислении упорядоченного набора перечисление продолжается в том порядке. Для NSArray, это означает, что первая передача будет для объекта в индексе 0, второе для объекта в индексе 1, и т.д. Если необходимо отслеживать текущий индекс, просто считать итерации, поскольку они происходят:

    int index = 0;
    for (id eachObject in array) {
        NSLog(@"Object at index %i is: %@", index, eachObject);
        index++;
    }

Даже если набор является непостоянным, Вы не можете видоизменить набор во время быстрого перечисления. При попытке добавить или удалить собранный объект из цикла, то Вы генерируете исключение на этапе выполнения.

Большинство наборов также поддерживает объекты перечислителя

Также возможно перечислить многих Какао и Сенсорные наборы Какао при помощи NSEnumerator объект.

Можно спросить NSArray, например, для objectEnumerator или a reverseObjectEnumerator. Возможно использовать эти объекты с быстрым перечислением, как это:

    for (id eachObject in [array reverseObjectEnumerator]) {
        ...
    }

В этом примере цикл выполнит итерации по собранным объектам в обратном порядке, таким образом, последний объект будет первым и т.д.

Также возможно выполнить итерации через содержание путем вызова перечислителя nextObject метод неоднократно, как это:

    id eachObject;
    while ( (eachObject = [enumerator nextObject]) ) {
        NSLog(@"Current object is: %@", eachObject);
    }

В этом примере, a while цикл используется для установки eachObject переменная к следующему объекту для каждого проходит через цикл. Когда больше нет оставленных объектов, nextObject метод возвратится nil, который оценивает как логическое значение лжи так остановки цикла.

Как с быстрым перечислением, Вы не можете видоизменить набор при перечислении. И, поскольку Вы могли бы собрать из имени, это быстрее для использования быстрого перечисления, чем использовать объект перечислителя вручную.

Много наборов основанное на опорном блоке перечисление

Также возможно перечислить NSArray, NSSet и NSDictionary использование блоков. Блоки покрыты подробно в следующей главе.