Массивы: упорядоченные наборы
Массивам упорядочивают наборы любого вида объекта. Например, объекты, содержавшиеся массивом в рисунке 1, могут быть любой комбинацией объектов кошки и собаки, и если массив является непостоянным, можно добавить больше объектов собаки. Набор не должен быть гомогенным.
Основные принципы массива
NSArray
объект управляет неизменным массивом — т.е. после создания массива Вы не можете добавить, удалить или заменить объекты. Можно, однако, изменить сами отдельные элементы (если они поддерживают модификацию). Переменчивость набора не влияет на переменчивость объектов в наборе. Если массив редко изменяется или изменяет оптовую торговлю, необходимо использовать неизменный массив.
NSMutableArray
объект управляет непостоянным массивом, позволяющим дополнение и удаление записей, выделяя память по мере необходимости. Например, данный NSMutableArray
объект, содержащий просто единственный объект собаки, можно добавить другую собаку, или кошку или любой другой объект. Вы можете также, как с NSArray
возразите, измените имя собаки — и в целом, что-либо, что можно сделать с NSArray
объект можно сделать с NSMutableArray
объект. Необходимо использовать непостоянный массив, если массив изменяется инкрементно или является очень большим — поскольку большое количество занимает больше времени для инициализации.
Можно легко создать экземпляр одного типа массива от другого использования инициализатора initWithArray:
или конструктор удобства arrayWithArray:
. Например, если у Вас есть экземпляр NSArray
, myArray
, можно создать непостоянную копию следующим образом:
NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray]; |
В целом Вы инстанцируете массива путем отправки одного из array...
сообщения любому NSArray
или NSMutableArray
класс. array...
сообщения возвращают массив, содержащий элементы, в которых Вы передаете как параметры. И когда Вы добавляете объект к NSMutableArray
объект, объект не копируется, (если Вы не передаете YES
как параметр initWithArray:copyItems:
). Скорее сильная ссылка к объекту добавляется к массиву. Для получения дополнительной информации о копировании и управлении памятью, посмотрите Копирование Наборов.
В NSArray
, два основных метода —count
и objectAtIndex:
— обеспечьте основание для всех других методов в его интерфейсе:
count
возвращает число элементов в массиве.objectAtIndex:
предоставляет Вам доступ к элементам матрицы индексом, с индексными значениями, запускающимися в 0.
Непостоянные массивы
В NSMutableArray
, основные методы, упомянутые ниже, обеспечивают основание для его возможности добавить, заменить, и удалить элементы:
Если Вам не нужен объект, который будет помещен в определенный индекс или будет удален с середины набора, необходимо использовать addObject:
и removeLastObject
методы, потому что это быстрее, чтобы добавить и удалить в конце массива, чем в середине.
Другие методы в NSMutableArray
обеспечьте удобные способы вставить объект в слот в массиве и удалить основанное на объектах на его идентификационных данных или позиции в массиве, как проиллюстрировано в Перечислении 1.
Перечисление 1 , Добавляющее к и удаляющее из массивов
NSMutableArray *array = [NSMutableArray array]; |
[array addObject:[NSColor blackColor]]; |
[array insertObject:[NSColor redColor] atIndex:0]; |
[array insertObject:[NSColor blueColor] atIndex:1]; |
[array addObject:[NSColor whiteColor]]; |
[array removeObjectsInRange:(NSMakeRange(1, 2))]; |
// array now contains redColor and whiteColor |
Используя массивы
Можно получить доступ к объектам в массиве индексом с помощью objectAtIndex:
метод. Например, если у Вас есть массив NSString
объекты, можно получить доступ к третьей строке в массиве следующим образом:
NSString *someString = [arrayOfStrings objectAtIndex:2]; |
NSArray
методы objectEnumerator
и reverseObjectEnumerator
предоставьте последовательный доступ к элементам массива, отличаясь только в направлении перемещения через элементы. Точно так же NSArray
методы makeObjectsPerformSelector:
и makeObjectsPerformSelector:withObject:
позвольте Вам отправить сообщения во все объекты в массиве. В большинстве случаев быстрое перечисление должно использоваться, поскольку это быстрее и более гибко, чем использование NSEnumerator
или makeObjectsPerformSelector:
метод. Для больше на перечислении, посмотрите Перечисление: Пересечение Элементов Набора.
Можно извлечь подмножество массива (subarrayWithRange:
) или свяжите элементы массива NSString
объекты в единственную строку (componentsJoinedByString:
). Кроме того, можно сравнить два массива с помощью isEqualToArray:
и firstObjectCommonWithArray:
методы. Наконец, можно создать новый массив, содержащий объекты в существующем массиве и один или несколько дополнительных объектов с arrayByAddingObject:
или arrayByAddingObjectsFromArray:
.
Существует два основных метода, которые можно использовать, чтобы определить, присутствует ли объект в массиве, indexOfObject:
иindexOfObjectIdenticalTo:
. Существует также два варианта, indexOfObject:inRange:
и indexOfObjectIdenticalTo:inRange:
то, что можно использовать для поиска диапазона в массиве. indexOfObject:
методы тестируют на равенство путем отправки элементов в массиве isEqual:
сообщение; indexOfObjectIdenticalTo:
методы тестируют на равенство с помощью сравнения указателя. Различие проиллюстрировано в Перечислении 2.
Перечисление 2 , Ищущее объект в массиве
NSString *yes0 = @"yes"; |
NSString *yes1 = @"YES"; |
NSString *yes2 = [NSString stringWithFormat:@"%@", yes1]; |
NSArray *yesArray = [NSArray arrayWithObjects:yes0, yes1, yes2, nil]; |
NSUInteger index; |
index = [yesArray indexOfObject:yes2]; |
// index is 1 |
index = [yesArray indexOfObjectIdenticalTo:yes2]; |
// index is 2 |
Сортировка массивов
Вы, возможно, должны сортировать массив на основе некоторых критериев. Например, Вы, возможно, должны поместить много создаваемых пользователями строк в алфавитный порядок, или Вы, возможно, должны поместить числа в увеличение или уменьшение порядка. Рисунок 2 показывает массив, сортированный фамилией тогда имя. Какао обеспечивает удобные способы сортировать содержание массива, такое как дескрипторы вида, блоки и селекторы.
Сортировка с дескрипторами вида
Дескрипторы вида (экземпляры NSSortDescriptor
) обеспечьте удобный и абстрактный способ описать упорядочивание вида. Дескрипторы вида обеспечивают несколько полезных функций. Можно легко выполнить большинство операций вида с минимальным пользовательским кодом. Можно также использовать дескрипторы вида в сочетании с привязкой Какао для сортировки содержания, например, табличное представление. Можно также использовать их с Базовыми Данными для упорядочивания результатов запроса выборки.
Если Вы используете методы sortedArrayUsingDescriptors:
или sortUsingDescriptors:
, дескрипторы вида обеспечивают простой способ сортировать набор объектов с помощью многих их свойств. Учитывая массив словарей (пользовательские объекты работают таким же образом), можно сортировать его содержание фамилией тогда имя. Перечисление 3 показывает, как создать тот массив и затем вид с дескрипторами. (Рисунок 2 показывает иллюстрацию этого примера.)
Создание перечисления 3 и сортировка массива словарей
//First create the array of dictionaries |
NSString *last = @"lastName"; |
NSString *first = @"firstName"; |
NSMutableArray *array = [NSMutableArray array]; |
NSArray *sortedArray; |
NSDictionary *dict; |
dict = [NSDictionary dictionaryWithObjectsAndKeys: |
@"Jo", first, @"Smith", last, nil]; |
[array addObject:dict]; |
dict = [NSDictionary dictionaryWithObjectsAndKeys: |
@"Joe", first, @"Smith", last, nil]; |
[array addObject:dict]; |
dict = [NSDictionary dictionaryWithObjectsAndKeys: |
@"Joe", first, @"Smythe", last, nil]; |
[array addObject:dict]; |
dict = [NSDictionary dictionaryWithObjectsAndKeys: |
@"Joanne", first, @"Smith", last, nil]; |
[array addObject:dict]; |
dict = [NSDictionary dictionaryWithObjectsAndKeys: |
@"Robert", first, @"Jones", last, nil]; |
[array addObject:dict]; |
//Next we sort the contents of the array by last name then first name |
// The results are likely to be shown to a user |
// Note the use of the localizedCaseInsensitiveCompare: selector |
NSSortDescriptor *lastDescriptor = |
[[NSSortDescriptor alloc] initWithKey:last |
ascending:YES |
selector:@selector(localizedCaseInsensitiveCompare:)]; |
NSSortDescriptor *firstDescriptor = |
[[NSSortDescriptor alloc] initWithKey:first |
ascending:YES |
selector:@selector(localizedCaseInsensitiveCompare:)]; |
NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil]; |
sortedArray = [array sortedArrayUsingDescriptors:descriptors]; |
Концептуально и программно просто изменить упорядочивание вида и расположить именем тогда фамилию, как показано в Перечислении 4.
Сортировка перечисления 4 именем, фамилией
NSSortDescriptor *lastDescriptor = |
[[NSSortDescriptor alloc] initWithKey:last |
ascending:NO |
selector:@selector(localizedCaseInsensitiveCompare:)]; |
NSSortDescriptor *firstDescriptor = |
[[NSSortDescriptor alloc] initWithKey:first |
ascending:NO |
selector:@selector(localizedCaseInsensitiveCompare:)]; |
NSArray *descriptors = [NSArray arrayWithObjects:firstDescriptor, lastDescriptor, nil]; |
sortedArray = [array sortedArrayUsingDescriptors:descriptors]; |
В частности это прямо для создания дескрипторов вида из ввода данных пользователем.
В отличие от этого, Перечисление 5 иллюстрирует первую сортировку с помощью функции. Этот подход значительно менее гибок.
Сортировка перечисления 5 с функцией менее гибка
NSInteger lastNameFirstNameSort(id person1, id person2, void *reverse) |
{ |
NSString *name1 = [person1 valueForKey:last]; |
NSString *name2 = [person2 valueForKey:last]; |
NSComparisonResult comparison = [name1 localizedCaseInsensitiveCompare:name2]; |
if (comparison == NSOrderedSame) { |
name1 = [person1 valueForKey:first]; |
name2 = [person2 valueForKey:first]; |
comparison = [name1 localizedCaseInsensitiveCompare:name2]; |
} |
if (*(BOOL *)reverse == YES) { |
return 0 - comparison; |
} |
return comparison; |
} |
BOOL reverseSort = YES; |
sortedArray = [array sortedArrayUsingFunction:lastNameFirstNameSort |
context:&reverseSort]; |
Сортировка с блоками
Можно использовать блоки, чтобы помочь сортировать массив на основе пользовательских критериев. sortedArrayUsingComparator:
метод NSArray
сортирует массив в новый массив, с помощью блока для сравнения объектов. NSMutableArray
sortUsingComparator:
сортирует массив на месте, с помощью блока для сравнения объектов. Перечисление 6 иллюстрирует сортировку с блоком.
Блоки перечисления 6 упрощают пользовательскую сортировку массивов
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) { |
if ([obj1 integerValue] > [obj2 integerValue]) { |
return (NSComparisonResult)NSOrderedDescending; |
} |
if ([obj1 integerValue] < [obj2 integerValue]) { |
return (NSComparisonResult)NSOrderedAscending; |
} |
return (NSComparisonResult)NSOrderedSame; |
}]; |
Сортировка с функциями и селекторами
Перечисление 7 иллюстрирует использование методов sortedArrayUsingSelector:
,sortedArrayUsingFunction:context:
, и sortedArrayUsingFunction:context:hint:
. Самый сложный из этих методов sortedArrayUsingFunction:context:hint:
. Вид, которому подсказывают, является самым эффективным, когда у Вас есть большой массив (N записи), что Вы сортируете один раз и затем изменяетесь только немного (P дополнения и удаления, где P намного меньше, чем N). Можно снова использовать работу, которую Вы выполнили в исходном виде путем концептуального выполнения сортировки слиянием между «старыми» элементами N и «новыми» элементами P. Для получения надлежащей подсказки Вы используете sortedArrayHint
когда исходный массив был сортирован и держится за него, пока Вам не нужен он (когда Вы хотите обратиться массив после того, как это было изменено).
Сортировка перечисления 7 с помощью селекторов и функций
NSInteger alphabeticSort(id string1, id string2, void *reverse) |
{ |
if (*(BOOL *)reverse == YES) { |
return [string2 localizedCaseInsensitiveCompare:string1]; |
} |
return [string1 localizedCaseInsensitiveCompare:string2]; |
} |
NSMutableArray *anArray = |
[NSMutableArray arrayWithObjects:@"aa", @"ab", @"ac", @"ad", @"ae", @"af", @"ag", |
@"ah", @"ai", @"aj", @"ak", @"al", @"am", @"an", @"ao", @"ap", @"aq", @"ar", @"as", @"at", |
@"au", @"av", @"aw", @"ax", @"ay", @"az", @"ba", @"bb", @"bc", @"bd", @"bf", @"bg", @"bh", |
@"bi", @"bj", @"bk", @"bl", @"bm", @"bn", @"bo", @"bp", @"bq", @"br", @"bs", @"bt", @"bu", |
@"bv", @"bw", @"bx", @"by", @"bz", @"ca", @"cb", @"cc", @"cd", @"ce", @"cf", @"cg", @"ch", |
@"ci", @"cj", @"ck", @"cl", @"cm", @"cn", @"co", @"cp", @"cq", @"cr", @"cs", @"ct", @"cu", |
@"cv", @"cw", @"cx", @"cy", @"cz", nil]; |
// note: anArray is sorted |
NSData *sortedArrayHint = [anArray sortedArrayHint]; |
[anArray insertObject:@"be" atIndex:5]; |
NSArray *sortedArray; |
// sort using a selector |
sortedArray = |
[anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; |
// sort using a function |
BOOL reverseSort = NO; |
sortedArray = |
[anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; |
// sort with a hint |
sortedArray = |
[anArray sortedArrayUsingFunction:alphabeticSort |
context:&reverseSort |
hint:sortedArrayHint]; |
Фильтрация массивов
NSArray
и NSMutableArray
классы обеспечивают методы для фильтрации содержания массива. NSArray
обеспечивает filteredArrayUsingPredicate:
, который возвращает новый массив, содержащий объекты в получателе, соответствующие указанный предикат. NSMutableArray
добавляет filterUsingPredicate:
, который оценивает содержание получателя против указанного предиката и оставляет только объекты тем соответствием. Эти методы проиллюстрированы в Перечислении 8. Для больше о предикатах, см. Руководство по программированию Предиката.
Перечисление 8 , Фильтрующее массивы с предикатами
NSMutableArray *array = |
[NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil]; |
NSPredicate *bPredicate = |
[NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"]; |
NSArray *beginWithB = |
[array filteredArrayUsingPredicate:bPredicate]; |
// beginWithB contains { @"Bill", @"Ben" }. |
NSPredicate *sPredicate = |
[NSPredicate predicateWithFormat:@"SELF contains[c] 's'"]; |
[array filterUsingPredicate:sPredicate]; |
// array now contains { @"Chris", @"Melissa" } |
Можно также отфильтровать массив с помощью NSIndexSet
объект. NSArray
обеспечивает objectsAtIndexes:
, который возвращает новый массив, содержащий объекты в индексах в предоставленном индексном наборе. NSMutableArray
добавляет removeObjectsAtIndexes:
, который позволяет Вам фильтровать массив на месте с помощью индексного набора. Для получения дополнительной информации об индексных наборах посмотрите Индексные Наборы: Хранение Индексов в Массив.
Массивы указателей
NSPointerArray
класс сконфигурирован по умолчанию для содержания, возражает очень как NSMutableArray
делает, за исключением того, что это может содержать nil
значения и что count
метод отражает тех nil
значения. Это также позволяет дополнительные возможности хранения, которые можно адаптировать для конкретных случаев, такой как тогда, когда Вам нужны усовершенствованные опции управления памятью или когда Вы хотите содержать определенный тип указателя. Например, массив указателей на рисунке 3 сконфигурирован для содержания слабых ссылок на его содержание. Можно также указать, хотите ли Вы скопировать объекты, ввел в массив.
Можно использовать NSPointerArray
возразите, когда Вы хотите упорядоченный набор, использующий слабые ссылки. Например, предположите, что у Вас есть глобальный массив, содержащий некоторые объекты. Поскольку глобальные объекты никогда не собираются, ни одно из его содержания не может быть освобождено, если они не сохранены слабо. Массивам указателей, сконфигурированным для содержания объектов слабо, не принадлежит их содержание. Если нет никаких сильных ссылок к объектам в таком массиве указателей, те объекты могут быть освобождены. Например, массив указателей на рисунке 3 содержит слабые ссылки на свое содержание. Возразите D, и Объект E будет освобожденный.
Для создания массива указателей создайте или инициализируйте его использование pointerArrayWithOptions:
или initWithOptions:
и надлежащее NSPointerFunctionsOptions
опции. Альтернативно можно инициализировать его использование initWithPointerFunctions:
и надлежащие экземпляры NSPointerFunctions
. Для получения дополнительной информации о различных опциях функций указателя посмотрите Опции Функции Указателя.
NSPointerArray
класс также определяет много конструкторов удобства для создания массива указателей с сильными или слабыми ссылками на его содержание. Например, pointerArrayWithWeakObjects
создает массив указателей, содержащий слабые ссылки на его содержание. Если Вы храните объекты, эти конструкторы удобства должны только использоваться.
Для конфигурирования массива указателей для использования произвольных указателей можно инициализировать его с обоими NSPointerFunctionsOpaqueMemory
и NSPointerFunctionsOpaquePersonality
опции. Например, можно добавить указатель на int
значение с помощью подхода, показанного в Перечислении 9.
Массив указателей перечисления 9 сконфигурирован для необъектных указателей
NSPointerFunctionsOptions options=(NSPointerFunctionsOpaqueMemory | |
NSPointerFunctionsOpaquePersonality); |
NSPointerArray *ptrArray=[NSPointerArray pointerArrayWithOptions: options]; |
[ptrArray addPointer: someIntPtr]; |
Можно тогда получить доступ к целому числу, как показывают ниже.
NSLog(@" Index 0 contains: %i", *(int *) [ptrArray pointerAtIndex: 0] ); |
Когда сконфигурировано для использования произвольных указателей массиву указателей связали риски с использованием указателей. Например, если указатели относятся к стековым данным, создаваемым в функции, те указатели не допустимы за пределами функции, даже если массив указателей. Попытка получить доступ к ним приведет к неопределенному поведению.