Чтение онлайн

на главную - закладки

Жанры

Программирование на Objective-C 2.0
Шрифт:

Возможно, вы не хотите записывать объект непосредственно в файл с помощью метода archiveRootObject:ToFile:, как в предыдущих примерах. Например, вам нужно собрать некоторые объекты и сохранить их в одном архивном файле. Это можно сделать с помощью обобщенного класса объектов потока данных (data stream) NSData.

Как говорилось в главе 16, объект класса NSData можно использовать для ре-зервирования области памяти для сохранения данных. Эту область памяти можно использовать, например, для временного хранения данных, которые будут последовательно записываться в файл, или для хранения содержимого файла, считанного с диска. Проще всего создать мутабельную область данных с помощью метода data. dataArea = [NSMutableData data];

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

В качестве простого примера предположим, что нужно архивировать в од-ном

файле адресную книгу и один из объектов класса Foo. Предположим также, что мы добавили методы архивации с ключами в классы AddressBook и AddressCard (см. программу 19.9). #import <Foundation/NSObject.h> #import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSString.h> #import < Foundation/NSKeyedArchiver. h> #import <Foundation/NSCoder.h> #import <Foundation/NSData.h> #import "AddressBook.h" #import Too.h" int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Foo *myFoo1 = [[Foo alloc] init]; Foo *myFoo2; NSMutableData *dataArea; NSKeyedArchiver *archiver; AddressBook *myBook; // Вставьте здесь код из программы 19.7 для создания в myBook // адресной книги, содержащей четыре адресные карточки [myFool setStrVal: @"This is the string"]; [myFool setlntVal: 12345]; [myFool setFloatVal: 98.6]; // Создание области данных и ее присоединение к объекту NSKeyedArchiver dataArea = [NSMutableData data]; archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: dataArea]; // Теперь можно начать архивацию объектов [archiver encodeObject: myBook forKey: @"myaddrbook"]; [archiver encodeObject: myFool forKey: @"myfoor]; [archiver finishEncoding]; // Запись архивируемой области данных в файл if ([dataArea writeToFile: @"myArchive" atomically: YES encoding: NSUTF8Encoding error: nil] == NC) NSLog (@"Archiving failed!"); (Архивация на выполнена) [archiver release]; [myFool release]; [pool drain]; return 0; }

После выделения памяти для объекта NSKeyedArchiver передается сообщение initForWritingWithMutableData:, чтобы указать область, в которую будут записываться архивируемые данные; это область NSMutabledata с именем dataArea, которая была создана выше. Сохраненному в архиваторе объекту NSKeyedArchiver можно передавать теперь сообщения кодирования для архивации объектов в программе. На самом деле, архивация и сохранение все кодируемых сообщений выполняется в указанной области данных, пока не получено сообщение finishEncoding.

В данном случае кодируются два объекта: наша адресная книга и объект класса Foo. Для этих объектов можно использовать encodeObjectiforKey:, поскольку мы ранее реализовали методы кодирования (encoder) и кодирования (decoder) для классов AddressBook, AddressCard и Foo.

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

Область с именем dataArea теперь содержит наши архивированные объекты в форме, которую можно записать в файл. В выражении с сообщением [dataArea writeToFile: @"myArchive" atomically: YES encoding: NSUTF8Encoding error: nil]

передается сообщение writeToFtle:atomically:encoding:error: потоку данных для записи его данных в указанный файл с именем myArchive.

Как видно из части с оператором if, метод writeToFi(e:atomicalfy:encoding:error: возвращает значение YES типа BOOL, если операция записи успешно выполнена, и значение N0, если ее не удалось выполнить (например, был указан неверный путь к файлу или переполнена файловая система).

Восстановление данных из архивного файла осуществляется просто: нужно выполнить все действия в обратном порядке. Во-первых, нужно выделить, как и раньше, область данных, затем в эту область данных прочитать архивный файл. После этого мы создаем объект NSKeyedUnarchiver и сообщаем ему, что требуется декодировать данные из указанной области. Для извлечения и декодирования архивированных объектов нужно вызвать методы декодирования, а по окончании - передать сообщение finishDecoding объекту NSKeyedUnarchiver. Все это выполняется в программе 19. К). #import <Foundation/NSObject.h> #import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSString.h> #import <Foundation/NSKeyedArchiver.h> #import <Foundation/NSCoder.h> #import <Foundation/NSData.h> #import "AddressBook.h" #import "Foo.h" * pool = [[NSAutoreleasePool alloc] inrt]; *dataArea; *unarchiver; *myFoo1; *myBook; // Чтение архива и присоединение к нему // объекта NSKeyedUnarchiver dataArea = [NSData dataWithContentsOfFile: @"myArchive"]; if (! dataArea) { NSLog (@"Can’t read back archive file!"); Return (1); } unarchiver = [[NSKeyedllnarchiver alloc] initForReadingWithData: dataArea]; // Декодирования объектов, которые мы сохранили ранее

в этом архиве myBook = [unarchiver decodeObjectForKey: @nmyaddrbook"]; myFool = [unarchiver decodeObjectForKey: @"myfoo1"]; [unarchiver finishDecoding]; [unarchiver release]; // Проверка того, что восстановление успешно выполнено [myBook list]; NSLog ("%@\n%i\n%g", [myFool strVal], [myFool intVal], [myFool floatVal]); [pool release]; return 0; }

Вывод программы 19.10 ======== Contents of: Steve's Address Book — Jamie Baker jbaker@hitmail.com Julia Kochan jewls337@axlc.com Stephen Kochan steve@steve_kochan.com Tony lannino tony.iannino@techfitness.com This is the string 12345 98.6

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

В программе 18.2 мы пытались создать копию массива, содержащего мутабель- ные строковые элементы, и создали поверхностную (shallow) копию этого мас-сива — копировались не сами строки, а только ссылки на них.

Возможности архивации Foundation позволяют создать глубокую (deep) ко-пию объекта. Например, в программе 19.11 выполняется копирование dataAnay в dataArray2 путем архивации dataAnay в буфер и его последующей деархивании с присваиванием результата массиву dataArray2. Нам не нужно задействовать файл для этого процесса; архивацию и деархивацию можно выполнять в памяти. #import <Foundation/NSObject.h> #import <Foundation/NSAutoreleasePool. h> #import <Foundation/NSString.h> #import <Foundation/NSKeyedArchiver.h> #import <Foundation/NSArray.h> int main (int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSData *data; NSMutableArray *dataArray = [NSMutableArray arrayWithObjects: [NSMutableString stringWithString; @"one"], [NSMutableString stringWithString; @"two"], [NSMutableString stringWithString: @ "three"], nil ]; NSMutableArray *dataArray2; NSMutableString *mStr; // Создание глубокой копии с помощью архиватора data = [NSKeyedArchiver archivedDataWithRootObject: dataArray]; dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData: data]; mStr = [dataArray2 objectAtlndex: 0]; [mStr appendString: @"ONE"]; NSLog (@"'dataArray:"); for ( NSString *elem in dataArray ) NSLog (n%@", elem); NSLog (@"\ndataArray2: "); for ( NSString *elem in dataArray2 ) NSLog ("%@"\ elem); [pool drsin]; return 0; }

Вывод программы 19.11 dataArray: one two three dataArray2: oneONE two three

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

Операция копирования в программе 19.11 выполняется с помощью следующих двух строк. data - [NSKcycdArchiver archivedDataWithRootObject: dataArray]; dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData: data];

Мы можем избежать промежуточного присваивания и выполнить копиро-вание с помощью одного оператора. dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData; [NSKeyedArchiver archivedDataWithRootObject: dataArray]];

Этот подход полезен для создания глубокой копии объекта или объекта, который не поддерживает протокол NSCopying. Упражнения

В главе 15 в программе 15.7 была создана таблица простых чисел. Внесите изменения в эту программу, чтобы записать результирующий массив в виде списка свойств ХМ L в файл primes.pl. Проверьте содержимое этого файла.

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

Внесите изменения в программу 19.2, чтобы вывести содержимое одного из списков свойств XML (файлы .plist), сохраненного в папке /Library/Preferences.

Напишите программу чтения архивированной адресной книги (AddressBook) и выполните поиск записи в соответствии с именем, указанным в командной строке, например $ lookup gregory

Часть III. Cocoa и SDK iPhone Глава 20. Введение в Cocoa

На протяжении этой книги мы разрабатывали программы, которые имеют до-вольно простой пользовательский интерфейс. Для вывода сообщений на кон-соль мы использовали процедуру @@ NSLog. Это действительно полезная про-цедура, но ее возможности ограничены. Другие программы, которые мы используем на своих Маках, имеют намного более удобный интерфейс. Репу-тация компьютеров Macintosh во многом основывается на дружественных пользовательских окнах и простоте использования. В своих приложениях мы можем использовать XCode вместе с приложением Interface Builder. Это сочета-ние образует мощную среду для разработки программ со средствами редакти-рования и отладки и удобным доступом к online-документации и позволяет легко разрабатывать сложные графические пользовательские интерфейсы (GUI).

Поделиться:
Популярные книги

Зодчий. Книга II

Погуляй Юрий Александрович
2. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга II

Я все еще не царь. Книга XXVI

Дрейк Сириус
26. Дорогой барон!
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Я все еще не царь. Книга XXVI

Ренегат космического флота

Борчанинов Геннадий
4. Звезды на погонах
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Ренегат космического флота

Свет Черной Звезды

Звездная Елена
6. Катриона
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Свет Черной Звезды

Искатель 3

Шиленко Сергей
3. Валинор
Фантастика:
попаданцы
рпг
фэнтези
5.00
рейтинг книги
Искатель 3

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Сотник

Вязовский Алексей
2. Индийский поход
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сотник

Последний Паладин. Том 6

Саваровский Роман
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 6

По дороге на Оюту

Лунёва Мария
Фантастика:
космическая фантастика
8.67
рейтинг книги
По дороге на Оюту

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Сфирот

Прокофьев Роман Юрьевич
8. Стеллар
Фантастика:
боевая фантастика
рпг
6.92
рейтинг книги
Сфирот

Путёвка в спецназ

Соколов Вячеслав Иванович
1. Мажор
Фантастика:
боевая фантастика
7.55
рейтинг книги
Путёвка в спецназ

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник

Законы Рода. Том 13

Андрей Мельник
13. Граф Берестьев
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 13