从NSKeyedArchiver加载Singleton的状态

rob*_*408 7 iphone singleton cocoa-touch objective-c nskeyedarchiver

我有一个班级,我已经成为一个单身,并且能够使用NSKeyedArchiver保存它的状态,但我无法绕过它将状态拉回来.

在我负载的功能中

Venue *venue = [Venue sharedVenue];
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
venue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];
Run Code Online (Sandbox Code Playgroud)

有了这段代码,decodeObjectForKey会返回什么?它实际上不是Venue的另一个实例,它不会加载任何已保存的值.在我将它转换为单件保存之前,加载工作正常.

Jon*_*ess 8

这是我认为这是错误的地方.您熟悉NSCoding并且通常通过使用encodeWithCoder:和initWithCoder:overrides使您的对象可编码来实现它.什么使这更简单的是你仍然可以使用NSCoding和NSCoders而不会覆盖这些方法.您可以编码共享对象的状态,而无需编码共享的obejct本身.这可以防止解码共享对象的尴尬问题.

这是我认为你可以做的一个例子:

@implementation MySharedObject
+ (id)sharedInstance {
    static id sharedInstance = nil;
    if (!sharedInstance) {
        sharedInstance = [[MyClass alloc] init];
    }
}

- (id)init {
    if ((self = [super init])) {
        NSData *data = /* probably from user defaults */
        if (data) { // Might not have any initial state.
            NSKeyedUnarchiver *coder = [[[NSKeyedUnarchiver alloc] initForReadingWithData:data] autorelease];
            myBoolean = [coder decodeBoolForKey:@"MyBoolean"];
            myObject = [[coder decodeObjectForKey:@"MyObject"] retain];
            [coder finishDecoding];
        }
    }
    return self;
}

- (void)saveState {
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *coder = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
    [coder encodeBool:myBoolean forKey:@"MyBoolean"];
    [coder encodeObject:myObject forKey:@"MyObject"];
    [coder finishEncoding]
    // Save the data somewhere, probably user defaults...   
}
@end
Run Code Online (Sandbox Code Playgroud)

这里我们有一个共享对象,它使用键控存档来持久化配置,但我们不对共享对象本身进行编码.这避免了解码单例类的第二个实例的尴尬问题.