Сохранение массива в файл Plist, содержащий пользовательские объекты iPhone - PullRequest
2 голосов
/ 13 ноября 2011

У меня есть класс с именем XYZ, наследующий от NSObject, и массив, который содержит объекты XYZ. Мне нужно записать этот массив в файл plist в каталог документов. Попробовав [array writeToFile ....], я обнаружил, что writeToFile завершается ошибкой, поскольку массив содержит пользовательские объекты класса XYZ.

Возможное решение этой проблемы - преобразовать объекты в NSData. Каковы разные способы достижения этого ?? Я обнаружил, что NSCoding подходит, но не могу понять, как его использовать. Любая помощь будет оценена.

Ответы [ 5 ]

9 голосов
/ 13 ноября 2011

После реализации encodeWithCoder: и initWithCoder: для пользовательского класса вот как написать и прочитать:

Запись:

NSError  *error;
NSData* archiveData = [NSKeyedArchiver archivedDataWithRootObject:yourClassInstance];
[archiveData writeToFile:filePath options:NSDataWritingAtomic error:&error];

Чтение:

NSData *archiveData = [NSData dataWithContentsOfFile:filePath];
YourClass *yourClassInstance = (NSArray*)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
9 голосов
/ 13 ноября 2011

В блоге Ray Wenderlich есть очень хорошее руководство, которое объясняет, как работать с NSCoding.

Просто вам просто нужно реализовать * - (void) encodeWithCoder: (NSCoder ) кодировать и * - (id) initWithCoder: (NSCoder ) методы в вашем объекте, которые уважает протокол NSCoding так:

// Header
@interface AnObject: NSObject <NSCoding>

// Implementation
- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:ivar1 forKey:@"ivar1"];
    [encoder encodeFloat:ivar2 forKey:@"ivar2"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super initWithCoder:coder];
    ivar1 = [[coder decodeObjectForKey:@"ivar1"] retain];
    ivar2 = [[coder decodeObjectForKey:@"ivar2"] retain];
    return self;
}

Вы также можете проверить официальную документацию здесь .

1 голос
/ 13 ноября 2011

Соответствие вашего класса XYZ протоколу NSCoding действительно очень подходит для того, что вы пытаетесь сделать. Для этого добавьте протокол NSCoding в объявление интерфейса вашего класса:

@interface XYZ <NSCoding>

Затем вам нужно реализовать encodeWithCoder: и initWithCoder: в вашей реализации. «Кодировать с помощью кодера» означает «взять текущее состояние вашего объекта и упаковать его в общий объект, называемый« кодировщик »». «Инициализация с кодером» означает «с учетом уже упакованного объекта кодера, сконфигурировать себя с данными, упакованными в кодер». В обоих этих методах «кодировщик» будет экземпляром NSCoder , который имеет довольно простой интерфейс для кодирования («упаковки») и декодирования («распаковки») основных типов.

Вот пример реализации:

@implementation XYZ
- (id)initWithCoder:(NSCoder*)encoder
{
    self = [self init];

    if (self)
    {
        self.myIntProperty = [encoder decodeIntForKey:@"myInt"];
    }

    return self;
}

– (void)encodeWithCoder:(NSCoder*)decoder
{
    [decoder encodeInt:self.myIntProperty forKey:@"myInt"];
}

@end
0 голосов
/ 13 ноября 2011

Это довольно просто.Для данного класса Foo:

#import <Foundation/Foundation.h>

@interface Foo : NSObject <NSCoding> {
    NSArray* bar_;
    NSUInteger baz_;
}

@property (nonatomic, retain) NSArray *bar;
@property (nonatomic, assign) NSUInteger baz;

@end

Все, что вам нужно сделать, чтобы соответствовать протоколу NSCoding, это реализовать сообщения initWithCoder: и decodeWithCoder:

#import "Foo.h"

@implementation Foo
@synthesize bar = bar_;
@synthesize baz = baz_;

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)encoder  {
    [encoder encodeObject:self.bar forKey:@"bar"];
    [encoder encodeInteger:self.baz forKey:@"baz"];
}

- (id)initWithCoder:(NSCoder *)decoder  {
    if ((self = [super init])) {
        self.bar = [decoder decodeObjectForKey:@"bar"];
        self.baz = [decoder decodeIntegerForKey:@"baz"];
    }
    return self;
}

- (void) dealloc {

    [bar_ release];
    [super dealloc];    
}

@end
0 голосов
/ 13 ноября 2011

Вам необходимо реализовать два метода: -initWithCoder: и -encodeWithCoder:.Прочитайте NSCoding документы;это довольно простые методы.В основном вы хотите закодировать / декодировать переменные вашего экземпляра ключом, соответствующим его имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...