decodeObjectForKey: всегда возвращает ноль - PullRequest
0 голосов
/ 24 февраля 2012

Я пытаюсь сохранить свой граф объектов в файл, а затем перезагрузить его позже, однако decodeObjectForKey: всегда возвращает nil для любого ключа, который я указываю.

Создается двоичный файл, в котором есть текст, читаемый человеком, т. Е. TitleTextColor, поэтому я думаю, что процесс архивации работает.

Я не понял, как работают NSKeyedArchiver и NSKeyedUnarchiver? Любая помощь будет оценена.

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeFloat:titleFontSize forKey:@"titleFontSize"];
    [encoder encodeObject:[UIColor orangeColor] forKey:@"titleTextColor"];
    [encoder encodeObject:lineSeparatorColor forKey:@"lineSeparatorColor"];
    [encoder encodeObject:bodyTextColor forKey:@"bodyTextColor"];
    [encoder encodeFloat:bodyTextFontSize forKey:@"bodyTextFontSize"];
    [encoder encodeObject:backgroundColor forKey:@"backgroundColor"];
    [encoder encodeObject:tintColor forKey:@"tintColor"];
    [encoder encodeInteger:bodyTextAlignment forKey:@"bodyTextAlignment"];

    [encoder encodeObject:@"Text" forKey:@"Text"];
}

+ (void) saveToFile {
    // Get the shared instance
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];    

    // Serialise the object
    NSData *serializedObject = [NSKeyedArchiver archivedDataWithRootObject:sharedInstance];

    // Get the path and filename of the file
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName];

    // Write the defaults to a file
    if (serializedObject) [serializedObject writeToFile:pathAndFileName atomically:YES];
}

+ (void) loadFromFile {
    // Get the shared instance
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];    

    // Get the path and filename of the file
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName];

    NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease];
    NSKeyedUnarchiver *defaults = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];

    // Set the properties of the shared instance
    NSString *test = [defaults decodeObjectForKey:@"Text"];
    NSLog (@"%@", test);
    sharedInstance.titleTextColor = [defaults decodeObjectForKey:@"titleTextColor"];

    [defaults release];
}

РЕДАКТИРОВАТЬ: на основе рекомендаций DarkDust:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        self.titleFontSize = [[aDecoder decodeObjectForKey:@"titleFontSize"] floatValue];
        self.titleTextColor = [aDecoder decodeObjectForKey:@"titleTextColor"];
        self.lineSeparatorColor = [aDecoder decodeObjectForKey:@"lineSeparatorColor"];
        self.bodyTextColor = [aDecoder decodeObjectForKey:@"bodyTextColor"];
        self.bodyTextFontSize = [[aDecoder decodeObjectForKey:@"bodyTextFontSize"] floatValue];
        self.backgroundColor = [aDecoder decodeObjectForKey:@"backgroundColor"];
        self.tintColor = [aDecoder decodeObjectForKey:@"tintColor"];
        self.bodyTextAlignment = [[aDecoder decodeObjectForKey:@"bodyTextAlignment"] intValue];
    }
    return self;
}

и создание нового экземпляра просто для проверки:

+ (void) loadFromFile {
    // Get the shared instance
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];    

    // Get the path and filename of the file
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName];

    NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease];
    PSYDefaults *newInstance =  [NSKeyedUnarchiver unarchiveObjectWithData:codedData];

    sharedInstance.titleTextColor = newInstance.titleTextColor;
}

РЕДАКТИРОВАТЬ - Обновление (необходимо для кодирования чисел и чисел в виде NSNumbers)

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithFloat:titleFontSize] forKey:@"titleFontSize"];
    [encoder encodeObject:titleTextColor forKey:@"titleTextColor"];
    [encoder encodeObject:lineSeparatorColor forKey:@"lineSeparatorColor"];
    [encoder encodeObject:bodyTextColor forKey:@"bodyTextColor"];
    [encoder encodeObject:[NSNumber numberWithFloat:bodyTextFontSize] forKey:@"bodyTextFontSize"];
    [encoder encodeObject:backgroundColor forKey:@"backgroundColor"];
    [encoder encodeObject:tintColor forKey:@"tintColor"];
    [encoder encodeObject:[NSNumber numberWithInt:bodyTextAlignment] forKey:@"bodyTextAlignment"];
}

Ответы [ 3 ]

6 голосов
/ 24 февраля 2012

Вы сериализовали с использованием одного корневого объекта, но вы пытаетесь десериализовать с помощью ключа, который не существует на этом уровне.

Вы хотите unarchiveObjectWithData:, как в:

NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease];
PSYDefaults *decodedDefaults = [NSKeyedUnarchiver unarchiveObjectWithData:codedData];

Обратите внимание, что вам также необходимо реализовать initWithCoder: в качестве аналога encodeWithCoder:. Несмотря на то, что кажется, что вы хотите иметь здесь одиночный файл, NSCoding требует создать здесь новый объект из-за [NSKeyedArchiver archivedDataWithRootObject:sharedInstance].

Если вы хотите en / декодировать поля без создания нового экземпляра PSYDefaults, вам необходимо использовать - [NSKeyedArchiver initForWritingWithMutableData:] и передать этот архив методу, аналогичному вашему encodeWithCoder: (но тогда вы должны дать ему другое имя). Затем вы напишете аналог, который читает поля обратно через NSKeyedUnarchiver, где вы используете decodeObjectForKey: и друзей для каждого поля.

Вы также можете прочитать руководство по программированию архивов и сериализаций Apple .

1 голос
/ 24 февраля 2012

Попробуйте сохранить ваш объект с помощью:

[NSKeyedArchiver archiveRootObject:object toFile:filePath];

и загрузить его с помощью:

[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

Я использую вышеописанные методы для сохранения NSDictionary с пользовательским объектом в файл.

А также у вас должна быть функция initWithCoder: (NSCoder *) декодер в вашем объекте.Которые декодируют данные, используя

[decoder decodeObjectFoyKey:yourKey];
0 голосов
/ 29 августа 2014

У меня была другая проблема с методом NSCoder's decodeObjectForKey при использовании FXForm - он вылетел без объяснения причин.

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

Причина была в проблемах с памятью.Обычно выглядит так, что когда в логах нет объяснения ошибки, это означает, что это проблема с памятью.Я забыл использовать правильный атрибут свойства - копировать.Я использовал назначить вместо этого.Это правильный код:

@interface MyClass : : NSObject <FXForm, NSCoding>

@property (nonatomic, copy) SomeClass *someObject;

@end

На всякий случай, если кто-то тоже столкнется с этой проблемой.

...