Как сохранить NSArray с настроенным объектом?
У меня есть NSMutableArray, если это строка хранилища, я могу читать и успешно писать, используя этот метод.
[array writeToFile:m_sApplicationPlistPath atomically:YES];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:m_sApplicationPlistPath];
но если мой массив добавит что-то, что не является простой строкой, например, я добавлю специальный объект в массив, например:
[array addObject:[[SpecialObject alloc] init]];
Я обнаружил, что не могу прочитать специальный объект, как я могу его решить, спасибо.
4 ответа
Вы можете заставить это работать, используя методы, определенные в NSKeyValueCoding
протокол для преобразования экземпляров вашего пользовательского класса в экземпляры NSDictionary
прежде чем писать их. Вы можете сделать подобное преобразование после прочтения plist-файла обратно, чтобы воссоздать объекты.
Вот пример, который преобразует массив экземпляров пользовательских Book
класс к массиву словарей, используя dictionaryWithValuesForKeys:
метод объявлен в NSKeyValueCoding
(и реализовано NSObject
так что все объекты наследуют это поведение):
+ (NSArray *)dictionariesFromBooks:(NSArray *)books
{
NSMutableArray *bookDicts = [NSMutableArray arrayWithCapacity:[books count]];
for (Book *currBook in books)
{
NSDictionary *currDict = [currBook dictionaryWithValuesForKeys:[Book keys]];
[bookDicts addObject:currDict];
}
return bookDicts;
}
Точно так же, вот метод, который заполняет экземпляры Book
с использованием NSKeyValueCoding
метод setValuesForKeysWithDictionary:
+ (NSArray *)booksFromDictionaries:(NSArray *)bookDicts
{
NSMutableArray *books = [NSMutableArray arrayWithCapacity:[bookDicts count]];
for (NSDictionary *currDict in bookDicts)
{
Book *currBook = [[Book alloc] init];
[currBook setValuesForKeysWithDictionary:currDict];
[books addObject:currBook];
[currBook release];
}
return books;
}
Приложив немного усилий, это можно сделать каскадом для вложенных пользовательских объектов. Например, если Book
содержал вложенный Author
Например, вы можете переопределить NSKeyValueCoding
такие методы, как setValue:forKey:
а также dictionaryWithValuesForKeys:
конвертировать экземпляр на лету.
Реализуйте протокол NSCoding. (encodeWithCoder и initWithCoder)
Если вы все еще не можете использовать метод writeToFile:atomically: тогда вам нужно сериализовать NSArray для получения данных, а затем записать их в файл.
NSData *data = NSKeyedArchiver archivedDataWithRootObject:theArray];
Я думаю, вы не можете сделать это, потому что метод [NSArray writeToFile:atomically:] использует списки свойств, которые доступны только для определенных типов данных (NSString, NSData, NSArray или NSDictionary).
Чтобы записать массив в файл, вы можете настроить SpecialObject на соответствие протоколу NSCoding, а затем сохранить массив, используя - [ NSKeyedArchiver archiveRootObject: toFile:], используя массив в качестве корневого объекта.
Из документов:
Если содержимое массива - это все объекты списка свойств (объекты NSString, NSData, NSArray или NSDictionary), файл, написанный этим методом, можно использовать для инициализации нового массива с помощью метода класса arrayWithContentsOfFile: или метода экземпляра initWithContentsOfFile:. Этот метод рекурсивно проверяет, что все содержащиеся объекты являются объектами списка свойств перед записью файла, и возвращает NO, если все объекты не являются объектами списка свойств, поскольку результирующий файл не будет допустимым списком свойств.