0

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

3 回答 3

6

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

你想要unarchiveObjectWithData:,如:

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

请注意,您还需要initWithCoder:作为encodeWithCoder:. 尽管看起来你想在这里有一个单例,但 NSCoding 要求在这里创建一个新对象,因为[NSKeyedArchiver archivedDataWithRootObject:sharedInstance].

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

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

于 2012-02-24T09:18:04.663 回答
1

尝试使用以下方法保存您的对象:

[NSKeyedArchiver archiveRootObject:object toFile:filePath];

并使用以下方法加载它:

[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

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

而且你应该在你的对象中有函数 initWithCoder:(NSCoder *)decoder 。哪个使用解码数据

[decoder decodeObjectFoyKey:yourKey];
于 2012-02-24T09:17:10.230 回答
0

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

以防万一有人也遇到这个问题。

于 2014-08-29T16:50:47.430 回答