Класс NSArray представляет упорядоченную коллекцию объектов. Свойство count определяет длину этой коллекции, а конкретный объект может быть извлечен из нее по номеру индекса с помощью метода obj ectAtlndex:. Индекс первого объекта в данной коллекции равен нулю, и поэтому индекс последнего ее элемента равен count - 1.

Начиная с версии 4.0 (Xcode 4.5) компилятора LLVM вызывать метод obj ectAtlndex: больше не нужно, а использовать вместо этого обозначение, напоминающее синтаксис языка С и других языков программирования, в которых определены массивы. Это обозначение состоит в том, чтобы присоединить квадратные скобки, в которые заключен номер индекса, к ссылке на массив, т.е. осуществить индексирование.

Так, если массив рер состоит из элементов @"Маппу", @"Мое" и 0"Jack", то обозначение элемента массива рер[2] равнозначно обозначению [pep objectAtIndex:2], а точнее — обозначению [pep objectAtlndexedSubscript: 2 ]. Дело в том, что такое обозначение индексирования приводит к тому, что любая ссылка, к которой присоединяется индекс, направляется методу objectAtlndexedSubscript:. Это, в свою очередь, означает, что любой класс, включая и ваши собственные, может реализовать метод objectAtlndexedSubscript: и тем самым стать пригодным для обозначения индексирования. Следует, однако, иметь в виду, что данный метод должен быть объявлен как открытый, чтобы компилятор разрешил такое обозначение индексирования.

Массив типа NSArray можно образовать по-разному, но, как правило, для этого предоставляется список объектов, которые он должен содержать. Как упоминалось в главе 3, синтаксис литералов, доступный с версии 4.0 (Xcode 4.4) компилятора LLVM, позволяет заключить этот список в выражение @ [. . . ]. Это еще один способ образовать массив типа NSArray, как показано ниже.

 

NSArray* pep = @[@"Manny", @"Мое", @"Jack"];

 

Класс NSArray является неизменяемым, но это совсем не означает, что объекты, содержащие в массиве типа NSArray, нельзя изменить. Напротив, это означает, что после того, как такой массив будет образован, из него уже нельзя удалить объект, ввести или заменить в нем объект по заданному индексу. Для выполнения подобных операций можно создать из текущего массива производный от него новый массив с исходным содержимым плюс или минус несколько объектов или же воспользоваться подклассом NSMutableArray, производным от класса NSArray.

Методам addObject: и replaceOb j ectAtlndex : withOb j ect: из класса NSMutableArray предоставляется то же обозначение индексирования, которое применяется в классе NSArray. В данном случае индексированная ссылка является значением, употребляемым в левой части выражения присваивания:

 

рер[3] - @"Zelda";

 

Вследствие этого массив типа NSMutableArray направляется методу setObject: atlndexedSubscript:. В классе NSMutableArray это реализуется таким образом, чтобы выражение рер [ 3 ] = @"Zelda" было равнозначно вызову метода addObject:, присоединяющему объект в конце массива, если массив рер состоит из трех элементов. Если массив рер состоит из более трех элементов, то выражение рер [3] = @"Zelda" равнозначно вызову метода replaceObj ectAtlndex: withOb j ect:. Если массив pep состоит из менее трех элементов, то данное выражение приводит к исключению, возникающему в связи с выходом за пределы массива.

Организовать обход (перечисление) каждого объекта в массиве можно с помощью конструкции for. . .in, описанной в главе 1. (Если попытаться изменить содержимое массива типа NSMutableArray при перечислении его элементов, возникнет исключение.) Для поиска объекта в таком массиве можно вызвать метод indexOfOb j ect: или indexOfObjectldenticalTo:. Первый из них производит проверку на равенство, вызывая метод isEqual:, тогда как во втором на равенство сравниваются указатели.

Те, кто имеет опыт программирования на других языках, могут упустить из виду такие служебные функции обработки массивов, как, например, функция шар (), которая составляет новый массив из результатов вызова метода для каждого объекта в текущем массиве. (Для вызова метода makeObjectsPerformSelector: требуется селектор, не возвращающий

значение, а для вызова метода enumerateObjectsUsingBlock: — блочная функция, также не возвращающая значение). В качестве выхода из этого положения можно создать пустой изменяемый массив и организовать перечисление исходного массива, вызывая соответствующий метод и присоединяя каждый раз результат к изменяемому массиву (см. ниже пример 10.1). Иногда вместо функции тар () можно также воспользоваться механизмом доступа к значениям по ключам, как поясняется в главе 12.

 

Пример 10.1. Создание одного массива путем перечисления другого массива

NSMutableArray* marr = [NSMutableArray new]; for (id obj in myArray) {

id result = [obj doSomething];

[marr addObject: result];

}

Имеется немало способов организовать поиск или фильтрацию массива с помощью блока, как показано ниже.

NSArray* pep = 0[0"Manny", @"Мое", @"Jack"];

NSArray* ems =

[pep objectsAtlndexes:[pep indexesOfObjectsPassingTest:

ABOOL(id obj, NSUInteger idx, BOOL *stop) {

return ([(NSString*}obj rangeOfString:@"m"

options:NSCaseInsensitiveSearch].location == 0);

}]];

 

Имеется также возможность получить отсортированный массив. Для этого можно предоставить разными способами правила сортировки или отсортировать массив непосредственно, если он изменяемый, как показано в примерах 3.1 и 3.2.

 

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


 

 

 

Добавить комментарий