Вандад Нахавандипур - iOS. Приемы программирования
Итак, учитывая сказанное, реализуем наш класс:
#import «Person.h»
NSString *const kFirstNameKey = @"FirstNameKey";
NSString *const kLastNameKey = @"LastNameKey";
@implementation Person
— (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject: self.firstName forKey: kFirstNameKey];
[aCoder encodeObject: self.lastName forKey: kLastNameKey];
}
— (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self!= nil){
_firstName = [aDecoder decodeObjectForKey: kFirstNameKey];
_lastName = [aDecoder decodeObjectForKey: kLastNameKey];
}
return self;
}
@end
Как видите, мы работаем с экземпляром класса NSCoder практически так же, как и со словарем. Разница заключается в том, что вместо словарного метода setValue: forKey: мы пользуемся encodeObject: forKey:, а вместо словарного метода objectForKey: задействуем decodeObjectForKey:. Отличия от словарей минимальны.
Итак, с этим классом все понятно. Теперь реализуем механизм архивации и деархивации, пользуясь двумя вышеупомянутыми классами. Мы собираемся сначала инстанцировать объект типа Person, затем заархивировать его, убрать из памяти, потом считать обратно из файла и убедиться, что разархивированное значение совпадает с тем, которое мы изначально записали в класс. Все это мы реализуем в делегате приложения, поскольку там это будет сделать проще всего:
#import «AppDelegate.h»
#import «Person.h»
@implementation AppDelegate
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
/* Определяем имя и фамилию, которые собираемся задать в объекте */
NSString *const kFirstName = @"Steven";
NSString *const kLastName = @"Jobs";
/* Определяем, где хотим заархивировать объект */
NSString *filePath = [NSTemporaryDirectory()
stringByAppendingPathComponent:@"steveJobs.txt"];
/* Инстанцируем объект */
Person *steveJobs = [[Person alloc] init];
steveJobs.firstName = kFirstName;
steveJobs.lastName = kLastName;
/* Архивируем объект в файл */
[NSKeyedArchiver archiveRootObject: steveJobs toFile: filePath];
/* Теперь разархивируем этот же класс в другой объект */
Person *cloneOfSteveJobs =
[NSKeyedUnarchiver unarchiveObjectWithFile: filePath];
/* Проверяем, совпадают ли имя и фамилия в разархивированном объекте
с именем и фамилией, которые находились в ранее архивированном объекте */
if ([cloneOfSteveJobs.firstName isEqualToString: kFirstName] &&
[cloneOfSteveJobs.lastName isEqualToString: kLastName]){
NSLog(@"Unarchiving worked");
} else {
NSLog(@"Could not read the same values back. Oh no!");
}
/* Временный файл нам больше не нужен, удаляем его */
NSFileManager *fileManager = [[NSFileManager alloc] init];
[fileManager removeItemAtPath: filePath error: nil];
self.window = [[UIWindow alloc]
initWithFrame: [[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Итак, при архивации просто используется метод класса archiveRootObject: toFile, относящийся к классу NSKeyedArchiver. Этот метод принимает объект и файл, в котором должно быть сохранено содержимое. Все просто. А если нужно разархивировать информацию? Не сложнее архивации. Нам просто нужно найти путь к заархивированному файлу, передать его методу класса unarchiveObjectWithFile:, относящемуся к классу NSKeyedUnarchiver. Всю остальную работу класс выполнит за вас.
См. также
Раздел 12.1.
Глава 13. Камера и библиотека фотографий
13.0. Введение
Большинство устройств с операционной системой iOS, допустим iPhone, оборудованы камерами. У самого нового iPhone две камеры, у других моделей может быть всего по одной. Некоторые устройства с операционной системой iOS не оснащены камерами. Класс UIImagePickerController позволяет программисту отображать для пользователя привычный интерфейс Camera и предлагать сделать снимок или записать видео. Фотографии или видеозаписи, выполненные с помощью класса UIImagePickerController, становятся доступны программисту.
В этой главе будет рассказано, как обеспечить пользователю возможность снимать фотографии и записывать видео прямо из приложения, получать доступ к фотографиям и видео, размещенным в библиотеке фотографий (Photo Library) на устройстве с iOS, например на iPod touch или iPad.
В симуляторе iOS интерфейс Camera не поддерживается. Все приложения, в которых требуется применять этот интерфейс, следует тестировать и отлаживать на настоящем устройстве с iOS, которое оборудовано камерой.
В этой главе мы сначала попытаемся определить, имеется ли камера на том устройстве с iOS, где используется наше приложение. Кроме того, вы можете выяснить, позволяет ли камера вам (программисту) делать фотоснимки, записывать видео или доступны обе эти функции. Для этого необходимо добавить фреймворк MobileCoreServices.framework к целевой сборке. Просто импортируйте его обобщающий фреймворк в ваше приложение, вот так:
#import «AppDelegate.h»
#import <MobileCoreServices/MobileCoreServices.h>
@implementation AppDelegate
<# Остаток вашего кода находится здесь #>
Далее перейдем к изучению других тем, в частности рассмотрим доступ к видео и фотографиям, расположенным в различных альбомах на устройстве с iOS. Речь идет о тех же самых альбомах, в которые можно попасть через приложение Photos (Фотографии), интегрированное в операционную систему iOS.
Но получить доступ к фотографии, находящейся в альбоме, проще, чем к видеозаписи. При работе с фотографиями мы получим адрес снимка и сможем просто загрузить эту информацию об изображении в экземпляр NSData либо прямо в экземпляр UIImage. В аналогичном случае с видео мы не получим адрес, по которому файл находится в файловой системе и с которого можно загрузить нужное видео. Вместо этого получим примерно такой адрес:
assets-library://asset/asset.MOV?id=10000 00004&ext=MOV
При работе с подобными адресами необходимо использовать фреймворк Assets Library (Библиотека ресурсов). Библиотека ресурсов открывает нам доступ к контенту, который обычно предоставляется через приложение Photos (Фотографии). Это, например, фотографии и видеоролики, отснятые пользователем. Кроме того, библиотека ресурсов может применяться для сохранения изображений и видео на устройстве. Потом эти фотографии и ролики будут доступны для библиотеки фотографий (Photo Library), а также других приложений, которым требуется доступ к этому контенту.
Чтобы все коды из этой главы правильно компилировались, убедитесь, что фреймворки Assets Library и Mobile Core Services включены во все ваши файлы с исходным кодом. Для этого можно импортировать заголовочные файлы в файлы с исходным кодом. Предполагается, что вы работаете с последней версией компилятора LLVM, в котором поддерживается работа с модулями:
#import «AppDelegate.h»
#import <MobileCoreServices/MobileCoreServices.h>
#import <AssetsLibrary/AssetsLibrary.h>
@implementation AppDelegate
<# Остаток вашего кода находится здесь #>
Чтобы все коды из этой главы правильно компилировались, выполните следующие шаги — так вы добавите в ваш проект фреймворк Assets Library.
1. В Xcode щелкните на ярлыке проекта.
2. Выберите цель, к которой вы хотите добавить фреймворк.
3. В верхней части интерфейса выберите Build Phases (Этапы сборки).
4. Нажмите кнопку + в нижнем левом углу раздела Link Binaries with Libraries (Связать двоичные файлы с библиотеками).
5. Выберите из списка фреймворк MobileCoreServices.framework.
6. Нажмите Add (Добавить).
Чтобы получить доступ к данным ресурса, имея ссылку на этот ресурс, выполните следующие шаги.
1. Выделите и инициализируйте объект типа ALAssetsLibrary. Объект из библиотеки ресурсов предоставляет специальную перемычку (Bridge), обеспечивающую доступ к тем видеороликам и фотографиям, которые доступны для приложения Photos (Фотографии).
2. Для доступа к ресурсу воспользуйтесь методом экземпляра assetForURL: resultBlock: failureBlock, относящимся к объекту библиотеки ресурсов (выделение и инициализация этого объекта были выполнены на шаге 1). Ресурс может представлять собой изображение, видео или любой другой объект, который Apple потенциально может добавить в библиотеку фотографий. Этот метод работает с блоковыми объектами. Подробнее о блоковых объектах и GCD рассказано в главе 7.
3. Высвободите тот объект библиотеки ресурсов, который был выделен и инициализирован на шаге 1.
На этом этапе у вас может возникнуть вопрос: как же именно я получаю доступ к данным ресурса? Параметр resultBlock метода экземпляра assetForURL: resultBlock: failureBlock, относящегося к объекту библиотеки ресурсов, должен указывать на блоковый объект, принимающий единственный параметр типа ALAsset. ALAsset — это класс, предоставляемый в библиотеке ресурсов, он инкапсулирует (включает в себя) ресурс, доступный для Photos (Фотографии) или любого другого приложения iOS, пытающегося использовать этот ресурс. Тема сохранения фотоснимков и видеороликов в библиотеке фотографий более подробно рассмотрена в разделах 13.4 и 13.5. О получении фотографий и видео из библиотеки фотографий и библиотеки ресурсов подробнее рассказано в разделах 13.6 и 13.7.