Spec-Zone .ru
спецификации, руководства, описания, API
Библиотека разработчика Mac Разработчик
Поиск

Получите основополагающие навыки программирования

Платформа Основы, как ее имя предполагает, является основополагающим инструментарием для всего программирования и для iOS и для OS X. Необходимо познакомиться с этим инструментарием, чтобы быть успешным разработчиком для этих платформ.

Основа определяет десятки классов и протоколов для множества целей, но три категории классов и протоколов выделяются как особенно основной принцип:

Наборы и объекты значения чрезвычайно важны в программировании Objective C, потому что Вы часто находите их как параметры и возвращаемые значения методов.

Корневой класс и объекты Objective C

В иерархии классов корневой класс не наследовался ни от какого другого класса, и все другие классы в иерархии в конечном счете наследовались от него. NSObject корневой класс иерархий классов Objective C. От NSObject, другие классы наследовали основной интерфейс к системе времени выполнения Objective C. И от NSObject, экземпляры этих классов получают свой фундаментальный характер, поскольку возражает Objective C.

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

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

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

Думайте с точки зрения объектов

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

image: ../Art/app_as_object_network.png

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

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

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

image: ../Art/communication_loosely_coupled.png

Создайте объекты

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

Создайте объект путем выделения и инициализации его

Для выделения объекта Вы отправляете alloc обменивайтесь сообщениями к классу объекта и возвратите «необработанный» (неинициализированный) экземпляр класса. При выделении объекта время выполнения Objective C выделяет достаточно памяти для объекта от виртуальной памяти приложения. В дополнение к выделению памяти время выполнения делает несколько других вещей во время выделения, таких как обнуление всех переменных экземпляра.

Сразу после выделения необработанного экземпляра, необходимо инициализировать его. Инициализация устанавливает начальное состояние объекта — т.е. его переменные экземпляра и свойства — к рыночной стоимости и затем возвращает объект. Цель инициализации состоит в том, чтобы возвратить применимый объект.

В платформах Вы найдете много методов, названных инициализаторами, инициализирующими объекты, но у них всех есть общие черты в их форме. Инициализаторы являются начинающимися методами экземпляра init и возвратите объект типа id. Корневой класс, NSObject, объявляет init метод, который наследовали все другие классы. Другие классы могут объявить свои собственные инициализаторы, каждого с его собственными ключевыми словами и типами параметра. Например, класс NSURL объявляет следующий инициализатор:

- (id)initFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir

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

NSURL *aURL = [[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory() isDirectory:YES];

Вы также выделили и инициализировали a Track объект в том, когда Вы создавали приложение TrackMix:

Track *aTrack = [[Track alloc] init];

Как безопасная практика программирования, можно протестировать возвращенный объект, чтобы проверить, что создавался объект. Если что-то происходит во время любого этапа, предотвращающего создание объекта, возвраты инициализатора nil. Несмотря на то, что Objective C позволяет Вам отправить сообщение в nil без негативных последствий (например, без вызванных исключительных ситуаций), Ваш код не мог бы работать как ожидалось, потому что не вызывают никакой метод. Необходимо использовать экземпляр, возвращенный инициализаторами, не тем, возвращенным alloc.

Создайте объект путем вызова метода фабрики классов

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

  • + (ввести)имя класса... (где имя класса исключает любой префикс),

Классы платформы Objective C иногда определяют методы фабрики классов, обычно соответствующие инициализаторам класса. Например, NSString объявляет следующие два метода:

- (id)initWithFormat:(NSString *)format, ...;
+ (id)stringWithFormat:(NSString *)format, ...;

Вот пример того, как Вы могли бы использовать эту фабрику классов NSString:

NSString *myString = [NSString stringWithFormat:@"Customer: %@", self.record.customerName];

Управляйте графом объектов для предотвращения утечек памяти

Объекты в программе Objective C составляют граф объектов: сеть объектов, сформированных отношениями каждого объекта с — или ссылки на — другие объекты. Ссылки, которые имеет объект, являются или непосредственными или (через объекты коллекции) one-many. Граф объектов важен, потому что это - фактор в долговечности объектов. Компилятор исследует силу ссылок в графе объектов и добавляет, сохраняют и выпускают сообщения, где это необходимо.

Вы формируете ссылки между объектами через основной C и конструкции Objective C, такие как глобальные переменные, переменные экземпляра и локальные переменные. Каждая из этих конструкций переносит с ним подразумеваемый объем; например, объем объекта, на который ссылается локальная переменная, является функциональным блоком, в котором он объявляется. Так же, как значительно, ссылки между объектами или сильны или слабы. Сильная ссылка указывает владение; относящемуся объекту принадлежит ссылочный объект. Слабая ссылка подразумевает, что относящемуся объекту не принадлежит ссылочный объект. Время жизни объекта определяется сколько сильных ссылок, там к нему. Объект не освобожден, пока существует сильная ссылка к нему.

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

image: ../Art/strong-ref-cycle-weak-ref.png

Для объектов в числе, если Вы повреждаете ссылку между A и B, тогда подграфом, состоящим из B, C, D, и жизней E на «навсегда», потому что эти объекты связаны циклом сильных ссылок. Путем представления слабой ссылки от E до B Вы повреждаете этот цикл сильной ссылки.

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

  • Делегаты

    @property (weak) id delegate;

    Вы узнаете о делегатах, и цели в статье Design Patterns “Оптимизировали Ваше Приложение с Шаблонами разработки”.

  • Выходы, которые не являются ссылками на объекты верхнего уровня

    @property (weak) IBOutlet NSString *theName;

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

    Свойства выхода для определенных классов платформы AppKit (например, NSWindow) исключения к этому правилу; они должны быть объявлены с assign опция.

  • Цели

    (void)setTarget:(id __weak)target
  • Ссылки на self в блоках

    __block typeof(self) tmpSelf = self;
    [self methodThatTakesABlock:^ {
        [tmpSelf doSomething];
    }];

    Клеточные виды сильная ссылка к переменным это получает. Если Вы используете self в блоке, клеточные виды сильная ссылка к self, итак, если self также имеет сильную ссылку к блоку (который он обычно делает), цикл сильной ссылки заканчивается. Для предотвращения цикла необходимо создать a weak (или __block) ссылка на self вне блока, как в примере выше.

Управляйте объектной переменчивостью

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

  • Неизменный объект неожиданно не изменится в значении при использовании его.

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

В платформах Objective C экземпляры неизменных классов обычно являются, инкапсулирующими наборы дискретных или буферизированных значений — например, массивы и строки. Эти классы обычно имеют непостоянные варианты с «Непостоянным» на их имена. Например, существует NSString (неизменный) класс и NSMutableString класс. Обратите внимание на то, что для некоторых неизменных объектов, инкапсулирующих дискретные значения, такой как NSNumber или NSDate, не имейте непостоянных вариантов класса.

Используйте непостоянные объекты вместо неизменного варианта, когда Вы будете ожидать изменять содержание объекта инкрементно и часто. Если Вы получаете объект от платформы, вводящейся как неизменный объект, уважайте тот тип возврата; не пытайтесь изменить объект.

Создайте и используйте объекты значения

Объект значения является объектом, инкапсулирующим примитивное значение (типа данных C) и предоставляющим услуги, связанные с тем значением. Объекты значения представляют скалярные типы в объектной форме. Платформа Основы предоставляет Вам следующие классы, генерирующие объекты значения для строк, двоичных данных, дат и времени, чисел и других значений:

  • NSString и NSMutableString

  • NSData и NSMutableData

  • NSDate

  • NSNumber

  • NSValue

Объекты значения важны в программировании Objective C. Вы часто встречаетесь с этими объектами как с параметрами и возвращаемыми значениями методов и функций, которые вызывает Ваше приложение. Путем передачи объектов значения различные части платформы или даже различных платформ могут обмениваться данными. Поскольку объекты значения представляют скалярные значения, можно использовать их в наборах и везде, где еще требуются объекты. Но вне их заурядности и последовательной необходимости, объекты значения имеют преимущество перед типами примитивов, которые они инкапсулируют: Они позволяют Вам выполнить определенные операции на инкапсулированном значении простым все же эффективным способом. NSString класс, например, имеет методы для поиска и замены подстрок для записи строк к файлам или (предпочтительно) URLs, и для построения путей файловой системы.

Иногда Вы будете считать его более эффективным и прямым для использования типов примитивов — т.е. значения, введенные как int (целое число), float, и т.д. Основной пример вычисляет значение. Следовательно, NSNumber и NSValue объекты менее распространены как параметры и возвращаемые значения в методах платформы. Следует иметь в виду, что многие платформы объявляют свои собственные типы числовых данных и используют эти типы для параметров и возвращаемых значений; примеры NSInteger и CGFloat. Необходимо использовать эти определенные с помощью платформы типы, где это необходимо, потому что они помогают Вам абстрагировать свой код далеко от базовой платформы.

Основы Использования объектов значения

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

int n = 5; // Value assigned to primitive type
NSNumber *numberObject = [NSNumber numberWithInt:n]; // Value object created from primitive type
int y = [numberObject intValue]; // Encapsulated value obtained from value object (y == n)

Большинство классов «значения» объявляет оба инициализатора и методы фабрики классов для создания их экземпляров. Некоторые классы —NSString и NSData в частности — также обеспечивают инициализаторы и методы фабрики классов для создания их экземпляров от примитивных данных, хранивших в локальных или удаленных файлах, а также от данных в памяти. Эти классы также обеспечивают дополнительные методы для записи строк и двоичных данных к файлам или к УКАЗАННЫМ URL расположениям. Код в следующем примере вызывает initWithContentsOfURL: метод для создания NSData объект от содержания файла, расположенного объектом URL; после использования данных код записывает объект данных обратно к файловой системе.

NSURL *theURL = // Code that creates a file URL from a string path...
NSData *theData = [[NSData alloc] initWithContentsOfURL:theURL];
// use theData...
[theData writeToURL:theURL atomically:YES];

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

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

Строки и литерал NSString

Как надмножество C, Objective C поддерживает те же соглашения для указания строк, как делает C. Другими словами, отдельные символы включаются одинарными кавычками, и строки символов окружаются двойными кавычками. Однако платформы Objective C обычно не используют струны до. Вместо этого они используют NSString объекты.

NSString класс обеспечивает объектную обертку для строк, таким образом предлагая такие преимущества как встроенное управление памятью для хранения строк произвольной длины, поддержки различных кодировок символов (особенно Unicode), и printf- утилиты форматирования стиля. Поскольку Вы обычно используете такие строки, Objective C обеспечивает краткую нотацию для создания NSString объекты от постоянных значений. Использовать это NSString литерал, только предшествуйте нормальной, дважды заключенной в кавычки строке со знаком at sign (@), как показано в следующих примерах:

// Create the string "My String" plus carriage return.
NSString *myString = @"My String\n";
// Create the formatted string "1 String".
NSString *anotherString = [NSString stringWithFormat:@"%d %@", 1, @"String"];
// Create an Objective-C string from a C string.
NSString *fromCString = [NSString stringWithCString:"A C string" encoding:NSASCIIStringEncoding];

Литералы NSNumber

Objective C также предлагает краткую нотацию для создания NSNumber объекты, устраняя необходимость вызвать инициализаторы или методы фабрики классов для создания таких объектов. Просто предшествуйте числовому значению со знаком at sign (@) и дополнительно следуйте за ним с индикатором типа значения. Например, для создания NSNumber объекты, инкапсулирующие целочисленное значение и двойное значение, соответственно, Вы могли записать следующее:

NSNumber *myIntValue    = @32;
NSNumber *myDoubleValue = @3.22346432;

Можно даже использовать NSNumber литералы для создания инкапсулировавших булевых и символьных ценностей.

NSNumber *myBoolValue = @YES;
NSNumber *myCharValue = @'V';

Можно создать NSNumber объекты, представляющие целых без знака, длинных целых, долгих длинных целых и плавание, оценивают путем добавления букв «U», «L», «LL» и «F», соответственно, к записанному нотами значению. Например, для создания NSNumber инкапсулируя значение плавающее, Вы могли записать следующее:

NSNumber *myFloatValue = @3.2F

Даты и время

NSDate объект отличается от других видов объектов значения из-за отличительной природы времени как примитивное значение. Объект даты инкапсулирует интервал, в секундах, с базисной даты. Та базисная дата является первым моментом от 1 января, 20:01 GMT.

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

  • NSCalendar и NSDateComponents— Можно связать дату с календарем и затем получить временные модули из календаря для даты, такие как год, месяц, час и день недели. Можно также выполнить calendrical вычисления.

  • NSTimeZone— Когда дата и время должна отразить часовой пояс области, можно связать объект часового пояса с календарем.

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

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

NSDate *now = [NSDate date]; // 1
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; // 2
[calendar setTimeZone:[NSTimeZone systemTimeZone]]; // 3
NSDateComponents *dc = [calendar components:(NSHourCalendarUnit|NSMinuteCalendarUnit|
    NSSecondCalendarUnit) fromDate:now];  // 4
NSLog(@"The time is %d:%d:%d", [dc hour], [dc minute], [dc second]); // 5
  1. Создает объект даты представление текущего момента.

  2. Создает объект, представляющий Григорианский календарь.

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

  4. Вызовы components:fromDate: метод на календарном объекте, передающем в объекте даты, создается на шаге 1. Этот вызов возвращает объект, содержащий час, минуту и вторые компоненты объекта даты.

  5. Регистрирует текущий час, минуту, и второй к консоли.

Несмотря на то, что этот пример регистрирует результат, предпочтительный подход для отображения информации о дате в пользовательском интерфейсе приложения должен использовать средства форматирования даты (экземпляры NSDateFormatter класс). Необходимо всегда использовать надлежащий класс и метод для calendrical вычислений; не делайте численных значений твердого кода для модулей, таких как минуты, часы и дни.

Создайте и используйте наборы

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

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

Различные типы наборов организуют свои содержащие в нем объекты отличительными способами:

  • NSArray и NSMutableArray— Массив является упорядоченным набором объектов. Вы получаете доступ к объекту путем указания его позиции (т.е. его индекса) в массиве. Первый элемент в массиве в индексе 0 (нуль).

  • NSDictionary и NSMutableDictionary— Словарь хранит свои записи как пары ключ/значение; ключ является уникальным идентификатором, обычно строка, и значение является объектом, который Вы хотите хранить. Вы получаете доступ к этому объекту путем указания ключа.

  • NSSet и NSMutableSet— Набор хранит неупорядоченный набор объектов с каждым объектом, происходящим только один раз. Вы обычно доступ возражаете в наборе путем применения тестов или фильтров к объектам в наборе.

image: ../Art/collections.png

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

Можно создать массивы и словари и получить доступ к значениям, из которых они содержат любого вызывающими методами NSArray и NSDictionary или при помощи специальных литералов контейнера Objective C и методов преобразования в нижний индекс. Следующие разделы описывают оба подхода.

Храните объекты в определенном порядке в массивах

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

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

NSArray класс дает Вам много инициализаторов и методов фабрики классов для создания и инициализации массивов, но несколько методов особенно распространены и полезны. Можно создать массив из серии объектов с arrayWithObjects:count: и arrayWithObjects: методы (и их соответствующие инициализаторы). С прежним методом второй параметр указывает число объектов в первом параметре; с последним методом Вы завершаете разделенную от запятой серию объектов с nil.

// Compose a static array of string objects
NSString *objs[3] = {@"One", @"Two", @"Three"};
// Create an array object with the static array
NSArray *arrayOne = [NSArray arrayWithObjects:&(*objs) count:3];
// Create an array with a nil-terminated list of objects
NSArray *arrayTwo = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil];

При создании непостоянных массивов можно использовать arrayWithCapacity: (или initWithCapacity:) метод для создания массива. Полный параметр дает подсказку классу об ожидаемом размере массива, таким образом делая массив более эффективным во время выполнения. Кроме того, массив может превысить указанную способность.

Можно также создать массивы с помощью контейнерного литерала @[…], где элементы между скобками разделяются от запятой объекты. Например, для создания массива, содержащего строку, число и дату, Вы могли записать следующее:

NSArray *myArray = @[ @"Hello World", @67, [NSDate date] ];

Доступ к объектам в массиве

Обычно Вы вызываете objectAtIndex: метод для доступа к объекту в массиве путем указания его индексной позиции (основанной на нуле) в массиве:

NSString *theString = [arrayTwo objectAtIndex:1]; // returns second object in array

NSArray дает Вам другие методы для доступа к или объектам в массиве или к их индексам. Например, существует lastObject, firstObjectCommonWithArray:, и indexOfObjectPassingTest:.

Вместо того, чтобы использовать метод NSArray для доступа к объекту в массиве можно использовать нотацию преобразования в нижний индекс. Например, для доступа к второму объекту в myArray (создаваемый выше), Вы могли бы записать что-то вроде этого:

id theObject = myArray[1];

Другая общая задача с массивами состоит в том, чтобы сделать что-то с каждым из объектов в массиве — это - процедура, известная как перечисление. Вы часто перечисляете массивы, чтобы определить, соответствуют ли объект или объекты определенное значение или условие и, если Вы делаете, завершаете действие с ним. Можно проявить один из трех подходов для перечисления массивов: быстрое перечисление, перечисление с блоком или использование NSEnumerator объект. Быстрое перечисление, поскольку его имя подразумевает, обычно быстрее, чем использование других методов для доступа к объектам в массиве. Быстрое перечисление является функцией языка, требующей определенного синтаксиса:

for (переменная типа in массив){ /* inspect переменная, do something with it */ }

Например:

NSArray *myArray = // get array
for (NSString *cityName in myArray) {
    if ([cityName isEqualToString:@"Cupertino"]) {
        NSLog(@"We're near the mothership!");
        break;
    }
}

Несколько NSArray методы перечисляют массивы с блоками, самым простым из них быть enumerateObjectsUsingBlock:. Блок имеет три параметра: текущий объект, его индекс и булево значение ссылкой, который, если установлено в YES завершает перечисление. Код в блоке выполняет точно ту же работу как код между фигурными скобками в операторе быстрого перечисления.

NSArray *myArray = // get array
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isEqual:@"Cupertino"]) {
        NSLog(@"We're near the mothership!");
        *stop = YES;
    }
}];

Управление непостоянными массивами

NSArray имеет другие методы, которые вид выстраивает, поисковые массивы, и вызовите метод на каждый объект в массиве.

Можно добавить объект к непостоянному массиву путем вызова addObject: метод; объект помещается в конце массива. Можно также использовать insertObject:atIndex: помещать объект в определенное расположение в непостоянном массиве. Можно удалить объект из непостоянного массива путем вызова removeObject: метод или removeObjectAtIndex: метод.

Можно также использовать нотацию преобразования в нижний индекс для вставки объекта в определенном расположении в непостоянном массиве.

NSMutableArray *myMutableArray = [NSMutableArray arrayWithCapacity:1];
NSDate *today = [NSDate date];
myMutableArray[0] = today;

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

Вы используете словарь, чтобы хранить объекты как пары ключ/значение — т.е. идентификатор (ключ) соединяется с объектом (значение). Словарям не упорядочивают наборы, потому что пары ключ/значение могут быть в любом порядке. Несмотря на то, что ключ может быть фактически чем-либо, это обычно - строка, описывающая значение — например, NSFileModificationDate или UIApplicationStatusBarFrameUserInfoKey (которые являются строковыми константами). Когда существуют открытые ключи, словари являются отличным способом передать информацию любого вида между объектами.

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

Через его инициализаторы и методы фабрики классов, NSDictionary класс дает Вам много способов создать словари, но два метода класса особенно распространены: dictionaryWithObjects:forKeys: и dictionaryWithObjectsAndKeys: (или их соответствующие инициализаторы). С прежним методом Вы передаете в массиве объектов и массиве ключей; ключи являются позиционально соответствующими их значениям. Со вторым методом Вы указываете первое объектное значение и затем его ключ, второе объектное значение и затем его ключ, и т.д.; Вы сигнализируете конец этой серии объектов с nil.

// First create an array of keys and a complementary array of values
NSArray *keyArray = [NSArray arrayWithObjects:@"IssueDate", @"IssueName", @"IssueIcon", nil];
NSArray *valueArray = [NSArray arrayWithObjects:[NSDate date], @"Numerology Today",
    self.currentIssueIcon, nil];
// Create a dictionary, passing in the key array and value array
NSDictionary *dictionaryOne = [NSDictionary dictionaryWithObjects:valueArray forKeys:keyArray];
// Create a dictionary by alternating value and key and terminating with nil
NSDictionary *dictionaryTwo = [[NSDictionary alloc] initWithObjectsAndKeys:[NSDate date],
    @"IssueDate", @"Numerology Today", @"IssueName", self.currentIssueIcon, @"IssueIcon", nil];

Как с массивами, можно создать NSDictionary объект при помощи контейнерного литерала @{ключ : значение, …}, где “…” указывает любое число пар ключ/значение. Например, следующий код создает неизменный объект словаря с тремя парами ключ/значение:

NSDictionary *myDictionary = @{
   @"name" : NSUserName(),
   @"date" : [NSDate date],
   @"processInfo" : [NSProcessInfo processInfo]
};

Доступ к объектам в словарях

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

NSDate *date = [dictionaryTwo objectForKey:@"IssueDate"];

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

NSString *theName = myDictionary[@"name"];

Управление непостоянными словарями

Можно вставить и удалить элементы в непостоянных словарях путем вызова setObject:forKey: и removeObjectForKey: методы. setObject:forKey: замены любое существующее значение для данного ключа. Эти методы быстры.

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

NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
mutableDict[@"name"] = @"John Doe";

Храните неупорядоченные объекты в наборах

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

Несмотря на то, что установленные объекты не так распространены в Objective C, программируя как словари и массивы, они - важный тип набора в определенных технологиях. В Базовых Данных (технология управления данными), когда Вы объявляете свойство для к - многие отношение, тип свойства должен быть NSSet или NSOrderedSet.

Упорядоченные наборы являются исключением к основному определению набора. В упорядоченном наборе порядок элементов в наборе важен. Тестирование на членство в упорядоченном наборе быстрее, чем это находится в массиве.

Проверьте объектные возможности во время выполнения

Самоанализ, мощная и полезная функция Objective C и NSObject класс, позволяет Вам изучить определенные вещи об объектах во время выполнения. Можно таким образом избежать ошибок в коде, таких как отправка сообщения к объекту, не распознающему его или предполагая, что объект наследовался от данного класса, когда это не делает.

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

  • Является ли это экземпляром определенного класса или подкласса

  • Реагирует ли это на сообщение

  • Соответствует ли это протоколу

Узнайте, Является ли Объектом Экземпляр Определенного Класса или его Подклассов

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

static int sum = 0;
for (id item in myArray) {
    if ([item isKindOfClass:[NSNumber class]]) {
        int i = (int)[item intValue];
        sum += i;
    }
}

isKindOfClass: метод берет объект типа Class в качестве параметра; для получения этого объекта вызовите class метод на классификационном знаке. Оцените булево значение, возвращенное этим методом, и продолжитесь соответственно.

NSObject объявляет другие методы для обнаружения информации об объектном наследовании. isMemberOfClass: метод, например, говорит Вам, является ли объект экземпляром определенного класса, тогда как isKindOfClass: говорит Вам, является ли объект элементом того класса или каким-либо из его происходящих классов.

Узнайте, реагирует ли объект на сообщение

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

if ([item respondsToSelector:@selector(setState:)]) {
    [item setState:[self.arcView.font isBold] ? NSOnState : NSOffState];
}

respondsToSelector: метод берет селектор в качестве своего параметра. Селектор является типом данных Objective C для идентификаторов во время выполнения методов; Вы указываете селектор с помощью @selector директива компилятора. В Вашем коде оцените булево значение, возвращенное этим методом, и продолжитесь соответственно.

Для идентификации сообщений объект отвечает на, вызывая respondsToSelector: обычно более полезно, чем оценка типа класса. Например, более свежая версия класса могла бы реализовать метод, не найденный в предыдущей версии.

Узнайте, соответствует ли объект протоколу

Чтобы сделать это, вызовите conformsToProtocol: метод на объекте.

- (void) setDelegate:(id __weak) obj {
    NSParameterAssert([obj conformsToProtocol:
        @protocol(SubviewTableViewControllerDataSourceProtocol)]);
    delegate = obj;
}

conformsToProtocol: метод берет идентификатор во время выполнения протокола в качестве параметра; Вы указываете этот идентификатор с помощью @protocol директива компилятора. Оцените булево значение, возвращенное этим методом, и продолжитесь соответственно. Отметьте, чем объект может соответствовать протоколу, не реализовывая его дополнительные методы.

Сравните объекты

Можно сравнить два объекта при помощи isEqual: метод. Объект, получающий сообщение, по сравнению с переданным - в объекте; если они - то же, возвраты метода YES. Например:

BOOL objectsAreEqual = [obj1 isEqual:obj2];
if (objectsAreEqual) {
    // do something...
}

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

Когда Вы сравниваете два объекта того же класса, что сравнено? Это зависит от класса. Корневой класс, NSObject, равенство указателя использования как основание сравнения. Подклассы на любом уровне могут переопределить реализацию своего суперкласса для базирования сравнения на специфичных для класса критериях, таких как объектное состояние. Например, если имя, фамилия и атрибуты даты рождения обоих объектов соответствуют, гипотетический объект Лица мог бы равняться другому объекту Лица.

Значение и классы набора платформы Основы объявляют методы сравнения формы isEqualToВвести:, где Тип является типом класса минус префикс «NS» — например, isEqualToString: и isEqualToDictionary:. Методы сравнения предполагают, что переданный - в объекте имеет данный тип, и повысьте исключение, если это не.

Объекты копии

Вы делаете копию объекта путем отправки a copy обменивайтесь сообщениями к нему:

NSArray *myArray = [yourArray copy];

Чтобы быть скопированным, класс принимающего объекта должен соответствовать NSCopying протокол. Если Вы хотите свои объекты быть copyable, необходимо принять и реализовать copy метод этого протокола.

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

Копирование поведения является определенным для класса и зависит от специфического характера экземпляра. Большинство классов реализует глубоко копирование, делающее копию всех переменных экземпляра и свойств; некоторые классы (например, классы набора) реализуют мелкое копирование, только копирующее ссылки на те переменные экземпляра и свойства.

Классы, имеющие непостоянные и неизменные варианты также, объявляют a mutableCopy метод для создания непостоянной копии объекта. Например, если Вы вызываете mutableCopy на NSString объект, Вы получаете экземпляр NSMutableString.