1

我有一堂课,我想在整个应用程序中保持持久设置。这个类定义为:

@interface Archive : NSCoder <NSCoding> {
    NSString *fromAddress;
    NSString *toAddress;
... more ...
}

@property(nonatomic,retain) NSString *fromAddress;
@property(nonatomic,retain) NSString *toAddress;

+ (Archive *)sharedArchive;

-(void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;

并实现为:

@synthesize fromAddress, toAddress;

+ (Archive *)sharedArchive
{
    if (sharedArchive == nil) {
        NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:@"mydata"];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        sharedArchive = [unarchiver decodeObjectForKey:@"myapp"];
        [unarchiver finishDecoding];
    }
    return sharedArchive;
}

+ (id)allocWithZone:(NSZone *)zone
{
    sharedArchive = [super allocWithZone:NULL];
    return sharedArchive;
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return NSUIntegerMax; 
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.fromAddress forKey:@"fromAddress"];
    [aCoder encodeObject:self.toAddress forKey:@"toAddress"];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [self initWithCoder:aDecoder];
    fromAddress = [[aDecoder decodeObjectForKey:@"fromAddress"] retain];
    toAddress = [[aDecoder decodeObjectForKey:@"toAddress"] retain];
    return self;
}

应用程序委托 applicationWillTerminate 方法:

- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:[Archive sharedArchive] forKey:@"myapp"];
    [archiver finishEncoding];
    [data writeToFile:@"myapp" atomically:YES];
}

我对存档/取消存档的概念很陌生。问题是我无法从数据文件中读回。我收到以下错误:

-[NSKeyedUnarchiver initForReadingWithData:]: 数据为 NULL

谁能解释我做错了什么?或者也许是保存/恢复持久数据的更好方法。我已经查看了 NSUserDefaults 类,但我认为这不适合我的情况……我不是要保存用户首选项。

4

2 回答 2

1

你只想保存这两个字符串?使用 NSUserDefaults。

如果您不想使用 NSUserDefaults,您应该提供真实路径而不是 @"myapp" 来 writeToFile 和 readFromFile。

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [libraryPath stringByAppendingPathComponent:@"myApp"];
[data writeToFile:path atomically:YES];

你也应该释放NSMutableData *dataNSKeyedUnarchiver *unarchiver

顺便说一句,[writeToFile:atomically:]返回一个 BOOL,告诉您写入是否成功。

btw2,- (void)applicationWillTerminate:(UIApplication *)application在启用多任务处理的 iOS4 上不会经常被调用。你也应该把你的保存功能放进去applicationDidEnterBackground:

于 2011-02-17T06:40:45.127 回答
0

@fluchtpunkt 做对了;“你只想保存这两个字符串?使用 NSUserDefaults。”

或者,更具体地说,如果:

有一门课,我想在整个应用程序中保持持久设置。

除非您需要保留大量数据(大型 BLOB 等),否则您应该使用NSUserDefaults.

依赖于应用程序终止/应用程序启动时的归档和取消归档充满了潜在的问题。应用程序并不总是被干净地终止,并且在启动时取消归档一堆“在整个应用程序中”使用的东西(即用于应用程序启动)只会让您的应用程序启动时间变慢。

如果您确实需要在启动之间保留大量状态,那么归档/取消归档当然可以工作。但是,您不应该归档与终止耦合;您真的希望用户在应用程序被强制退出、抛弃或设备硬重启时丢失数据(许多用户对此有不自然的癖好)?

于 2011-02-17T17:14:18.703 回答