NSKeyedArchiver писать XML (или другой человек для чтения)? - PullRequest
8 голосов
/ 30 октября 2009

Я пытался заставить NSKeyedArchiver записать мои данные в удобочитаемой форме (т.е. не в виде двоичного файла). Я понимаю, что могу использовать ...

setOutputFormat: NSPropertyListXMLFormat_v1_0

Но ... Я просто не могу понять синтаксис правильно, кто-нибудь может указать мне правильное направление?

NSData *artistData;

NSLog(@"(*) - Save All");
artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection ];
[artistData writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES];

EDIT

Я добавил setOutputFormat (см. Ниже), но я получаю предупреждение при компиляции, что мне не хватает?

warning: NSData  may not respond to 'setOutputFormat:'

Вот код, который я использовал.

NSLog(@"(*) - Save All");
artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection ];
[artistData setOutputFormat: NSPropertyListXMLFormat_v1_0];
[artistData writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES];

* 1015 Гэри *

Ответы [ 4 ]

17 голосов
/ 01 ноября 2009

Вот что вам нужно сделать:

NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver setOutputFormat:NSPropertyListXMLFormat_v1_0];
[archiver encodeObject:artistCollection forKey:@"root"];
[archiver finishEncoding];
[data writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES];
[archiver release];

Обратите внимание, что необходимо использовать [archiver encodeObject:artistCollection forKey:@"root"] вместо [archiver encodeRootObject:artistCollection];, как предложил Шон. Это потому, что NSKeyedArchiver не переопределяет NSCoder encodeRootObject: метод. Я считаю это ошибкой и сообщу об этом Apple.

Теперь реальный вопрос: почему вы хотите писать XML вместо двоичного формата по умолчанию? Если это для целей отладки, я предлагаю вам использовать TextWrangler , который позволит вам прозрачно редактировать двоичные файлы plist, как если бы они были XML.

2 голосов
/ 31 октября 2009

Сначала необходимо создать экземпляр NSKeyedArchiver, а не использовать удобный метод класса, который будет возвращать только NSData.

NSMutableData *data = [NSMutableData new];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

// set the one property you specifically wanted
[archiver setOutputFormat:NSPropertyListXMLFormat_v1_0];

// now encode (and finalize) the actual object - note that encodeRootObject: is inherited
// from NSCoder. I assume this works :)
[archiver encodeRootObject:artistCollection];
[archiver finishEncoding];

// now finally write it out - the resulting encoded stuff should be waiting in the data object
[data writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES];

// cleanup after ourselves
[archiver release];
[data release];

Отказ от ответственности: я написал этот код в поле ввода здесь и фактически не проверял его.

1 голос
/ 30 октября 2009

'archivedDataWithRootObject:' является методом класса, тогда как 'setOutputFormat' является методом экземпляра. Из документации для 'archivedDataWithRootObject:':

Объект NSData, содержащий закодированную форму графа объектов, корневым объектом которого является rootObject. Формат архива: NSPropertyListBinaryFormat_v1_0.

Что вам нужно сделать, это создать NSKeyedArchiver и кодировать корневой объект. Также убедитесь, что все содержимое вашей коллекции реализует «encodeWithCoder» и «initWithCoder». Увидеть Объекты кодирования и декодирования

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

[artistCollection writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES];

Обсуждение этого метода (как для NSDictionary, так и для NSArray):

Если содержимое получателя - это все объекты списка свойств (объекты NSString, NSData, NSArray или NSDictionary), файл, написанный этим методом, можно использовать для инициализации нового массива с помощью метода класса arrayWithContentsOfFile: или метода экземпляра initWithContentsOfFile: , Этот метод рекурсивно проверяет, что все содержащиеся объекты являются объектами списка свойств перед записью файла, и возвращает NO, если все объекты не являются объектами списка свойств, поскольку результирующий файл не будет действительным списком свойств. Blockquote

0 голосов
/ 30 октября 2009
[artistData setOutputFormat: NSPropertyListXMLFormat_v1_0];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...