iOS-приложения зачастую используют XML либо JSON для получения данных от веб-сервисов. Лично, для меня парсинг XML — процедура не очень приятная. Парсинг JSON немного приятнее, но тут приходится прибегать к использованию сторонних компонент. Далее мы рассмотрим еще один вариант.
Вступление
Как мы знаем, в iOS и MacOS X широко используются Property list файлы. Foundation позволяет «сохранять» экземпляры классов в этот формат. «Сохраняются» классы которые реализуют NSCoding-протокол. Некоторые из них это:
- NSString
- NSNumber
- NSDate
- NSData
- NSArray
- NSDictionary
А так же унаследованные от них. К тому же, никто не запрещает реализовать NSCoding в своих классах для последующей сериализации. Для чтения/записи файлов формата Property list не требуется никаких сторонних компонент, все уже есть в Foundation.
Ах, да. О чем это я? Я о альтернативе XML и JSON. Так вот, если веб-сервис умеет «отдавать» данные в формате Property list то парсинг и сохранение становится намного легче.
Примеры
Чтобы сохранить, к примеру, NSArray в plist (Property list) можно сделать вот так:
NSArray* array = ...;
[array writeToFile: @"file.plist" atomically:YES];
Как видим первый аргумент — это имя файла, второй определяет, записывать ли сразу в конечный файл либо записать в временный и скопировать на место нужного. Метод возвращает BOOL в зависмости от того успешно прошла запись или нет.
Чтобы «распарсить» plist есть несколько вариантов, в зависимости от ситуации. Если вам нужно открыть локальный файл, то:
+ (id)arrayWithContentsOfFile:(NSString *)aPath
Если получить какие-либо данные с веб-сервиса по URL то делаем так:
+ (id)arrayWithContentsOfURL:(NSURL *)aURL
К примеру, к NSDictionary можно применять похожие методы:
+ (id)dictionaryWithContentsOfFile:(NSString *)path
+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
Более сложная ситуация
С простым разобрались. Хорошо, если NSArray (или другая коллекция) содержит в себе экземпляры классов, которые поддерживают NSCoding. А если в коллекции находится что-то созданное своими руками? Правильный ответ — нужно заставить «это» следовать NSCoding протоколу.
Предположим у нас есть наш красс Customer. В объявлении надо написать, что он следует NSCoding. К примеру так:
@interface Customer : NSObject<NSCoding>
Далее нужно реализовать два метода — записи и чтения. Сначала рассмотрим метод записи. Предположим, что в классе Customer есть два поля — int m_ID и NSString* m_Name:
-(void) encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInt:m_ID forKey:@"ID"];
[aCoder encodeObject:m_Name forKey:@"Name"];
}
Как видим, нужно просто поставить в соответствие каждому полю какой-либо ключ. Теперь чтение:
-(id) initWithCoder:(NSCoder *)aDecoder {
self = [super init];
m_ID = [aDecoder decodeIntForKey:@"ID"];
m_Name = [[aDecoder decodeObjectForKey:@"Name"] retain];
return self;
}
Просто «забираем» значения по ключам, которыми сохраняли.
Итог
Возможно, вы спросите — зачем? Ведь есть JSON и XML. Использование «родных» для MacOS X и iOS файлов plist дает прирост в скорости «парсинга», т.е. JSON и XML обрабатываются дольше, чем plist.
К тому же метод с NSCoding можно использовать при сохранение каких-либо данных внутри приложения.
Похожие статьи
-
Audio Unit в iOS. Часть 3, накладываем эффект Delay
-
Audio Unit в iOS. Часть 2, строим граф и проигрываем файлы
-
Audio Unit в iOS. Часть 1, введение.
-
Используем Emoji в своих приложениях
-
Как вводить в UITextField только цифры?