decodeObjectForKey:始终返回nil

时间:2012-02-24 09:04:28

标签: iphone ios nskeyedarchiver nscoding

我正在尝试将对象图保存到文件中,然后在以后重新加载它,但是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;
}

编辑 - 更新(需要将浮点数和整数编码为NSNumber)

- (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 个答案:

答案 0 :(得分:6)

您使用单个根对象进行了序列化,但尝试使用该级别不存在的密钥进行反序列化。

您想要unarchiveObjectWithData:,如:

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

请注意,您还需要实施initWithCoder:作为encodeWithCoder:的对应部分。虽然看起来你想在这里有一个单例,但由于[NSKeyedArchiver archivedDataWithRootObject:sharedInstance],NSCoding要求在这里创建一个新对象。

如果您想在不创建PSYDefaults的新实例的情况下对字段进行解码/解码,则需要使用-[NSKeyedArchiver initForWritingWithMutableData:]并将该存档传递给类似于encodeWithCoder:的方法(但是你应该给它一个不同的名字然后)。然后你会写一个对手,通过NSKeyedUnarchiver读取字段,你可以使用decodeObjectForKey:和每个字段的朋友。

您可能还想阅读Apple的Archives and Serializations Programming Guide

答案 1 :(得分:1)

尝试使用以下方式保存对象:

[NSKeyedArchiver archiveRootObject:object toFile:filePath];

并使用以下方式加载:

[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

我使用上面的方法将带有自定义对象的NSDictionary保存到文件中。

你还应该在对象中使用函数initWithCoder:(NSCoder *)解码器。 使用

解码数据
[decoder decodeObjectFoyKey:yourKey];

答案 2 :(得分:0)

使用NSCoder's时,我遇到了decodeObjectForKey FXForm方法的另一个问题 - 它在没有任何解释的情况下崩溃了。

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

原因在于记忆问题。通常,看起来当日志中没有错误的解释时,这意味着,这是一个内存问题。我忘了使用正确的属性属性 - 复制。我改用了assign。这是正确的代码:

@interface MyClass : : NSObject <FXForm, NSCoding>

@property (nonatomic, copy) SomeClass *someObject;

@end

以防有人遇到这个问题。