Архивы

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

Архивы какао могут содержать объекты Objective C, скаляры, массивы, структуры и строки. Они не содержат типы, реализация которых варьируется через платформы, такой как union, void *, указатели функции и длинные цепочки указателей.

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

Кодеры

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

Кодер возражает чтению и объектам записи путем отправки одного из двух сообщений к объектам, которые будут кодироваться или декодироваться. Кодер отправляет encodeWithCoder: к объектам при создании архива и initWithCoder: при чтении архива. Эти сообщения определяются NSCoding протокол. Только объекты, класс которых соответствует NSCoding протокол может быть записан в архив. (Ссылка для каждого класса Какао указывает, принимает ли класс NSCoding протокол.), Когда объект получает одно из этих сообщений, объект передает сообщения обратно кодеру для сообщения кодера, возражающего или оценивающего, обычно переменные экземпляра, чтобы читать или записать затем. При кодировании объектов кодер записывает в архиве идентификационные данные класса объектов (или тип значений Objective C) и их позиция в иерархии.

Графы объектов, такой как один показанный на рисунке 1, излагают две проблемы кодеру: избыточность и ограничение. Решить эти проблемы, NSCoder представляет понятия корневых объектов и условных объектов, описанных в следующих разделах.

Корневой объект

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

Решить эту проблему, NSCoder представляет понятие корневого объекта. Корневой объект является начальной точкой графа объектов. Для кодирования графа объектов Вы вызываете NSCoder метод encodeRootObject:, передача в первом объекте закодировать. Каждый объект, закодированный в контексте этого вызова, прослежен. Если кодер просят закодировать объект несколько раз, кодер кодирует ссылку на первое кодирование вместо того, чтобы кодировать объект снова.

NSCoder не реализует поддержку корневых объектов; NSCoderреализация encodeRootObject: просто кодирует объект путем вызова encodeObject:. Это - ответственность своих конкретных подклассов отслеживать многократные ссылки на объекты, таким образом сохраняя структуру любых графов объектов.

Условные объекты

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

Решить эту дилемму, NSCoder представляет понятие условного объекта. Условный объект является объектом, который должен быть закодирован, только если он кодируется безусловно в другом месте в графе объектов. Условный объект кодируется путем вызова encodeConditionalObject:forKey:. Если все запросы для кодирования объекта выполнены с этими условными методами, объект не кодируется, и ссылки на него декодируют к nil. Если объект кодируется в другом месте, все условные ссылки декодируют к единственному закодированному объекту.

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

NSCoder не реализует поддержку условных объектов; NSCoderреализация encodeConditionalObject:forKey: просто кодирует объект путем вызова encodeObject:forKey:. Это - ответственность своих конкретных подклассов отслеживать условные объекты и не закодировать объекты, если они не необходимы.

Включенные архивы

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

Следующие разделы описывают, как использовать включенные архивы.

Именование значений

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

Общедоступные классы, такие как те в платформе, которая может быть разделена на подклассы, должны добавить префикс к строке имени для предотвращения коллизий с ключами, которые могут использоваться теперь или в будущем подклассами класса. Разумный префикс является полным именем класса. Классы какао используют префиксный «NS» в своих ключах, то же как префикс API, и тщательно удостоверяется, что нет никаких коллизий в иерархии классов. Другая возможность состоит в том, чтобы использовать ту же строку в качестве идентификатора пакета для платформы.

Необходимо избегать использования «$» как префикса для ключей. Включенный archiver и unarchiver используют ключи, снабженные префиксом «$» для внутренних значений. Несмотря на то, что они тестируют на и искажают определяемые пользователем ключи, имеющие префикс «$», эти издержки замедляют производительность архивации.

Подклассы также должны несколько знать о префиксе, используемом суперклассами для предотвращения случайных коллизий на ключевых именах. Подклассы классов Какао должны избежать непреднамеренно запускать свои ключевые имена с «NS». Например, не называйте ключ «NSString search options».

Возвращаемые значения для недостающих ключей

При декодировании, если Вы запрашиваете включенное значение, не существующее, unarchiver возвращает значение по умолчанию на основе типа возврата метода декодирования, который Вы вызвали. Значения по умолчанию являются эквивалентом нуля для каждого типа данных: nil для объектов, NO для булевских переменных, 0.0 за реалы, NSZeroSize для размеров, и т.д. Если необходимо обнаружить отсутствие включенного значения, используйте NSKeyedUnarchiver метод экземпляра containsValueForKey:, который возвращается NO если не присутствует предоставленный ключ. Когда значения по умолчанию достаточны, по причинам производительности необходимо избежать явно тестировать на ключи.

Введите приведения

NSKeyedUnarchiver поддержки ограничили приведение типа. Значение, закодированное как любой тип целого числа, быть им стандарт int или явное 32-разрядное или 64-разрядное целое число, может декодироваться с помощью любого из целочисленных методов декодирования. Аналогично, значение, закодированное как a float или double может декодироваться как любой a float или a double значение. При декодировании a double оцените как a float, Тем не менее, декодируемое значение теряет точность. Если закодированное значение является слишком большим для адаптации в принужденном декодируемом типе, метод декодирования бросает NSRangeException. Далее, при попытке принудить значение к несовместимому типу, такому как декодирование int как a float, метод декодирования бросает NSInvalidUnarchiveOperationException.

Управление версиями класса

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

Корневые объекты

encodeObject: и encodeObject:forKey: методы в состоянии отследить многократные ссылки на объекты в многократных графах объектов. Столько графов объектов или значений, сколько желаемый может быть закодирован на верхнем уровне включенного архива.

NSKeyedArchiver реализации archiveRootObject:toFile: и archivedDataWithRootObject: произвести архивы с графиком отдельного объекта. Эти архивы, однако, должны быть разархивированы с помощью NSKeyedUnarchiver методы unarchiveObjectWithFile: и unarchiveObjectWithData:.

Делегаты

NSKeyedArchiver и NSKeyedUnarchiver объекты могут иметь объекты делегата. Делегаты уведомляются, поскольку каждый объект кодируется или декодируется. Можно использовать делегатов для выполнения замен, заменяя один объект для другого, при желании.

Невключенные методы кодирования

Включенные archivers не должны обеспечивать имена для каждого значения, закодированного в архиве. NSKeyedArchiver и NSKeyedUnarchiver классы реализуют невключенное кодирование и декодирование методов, от которых они наследовались NSCoder. Использованию невключенных методов во включенном кодировании обескураживают.