使用单例并将其存档

时间:2011-02-17 06:27:58

标签: iphone sdk singleton nskeyedarchiver

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

@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:]:data为NULL

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

2 个答案:

答案 0 :(得分:1)

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

如果你不想使用NSUserDefaults,你应该为writeToFile和readFromFile提供真正的路径而不是@“myapp”。

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

您还应该发布NSMutableData *dataNSKeyedUnarchiver *unarchiver

btw,[writeToFile:atomically:]返回一个BOOL,告诉你写入是否成功。

btw2,在启用了多任务处理的iOS4上,不会经常调用- (void)applicationWillTerminate:(UIApplication *)application。您应该将保存功能放入applicationDidEnterBackground:

答案 1 :(得分:0)

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

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

  

有一个我想保留的课程   我的应用程序中的持久设置。

除非您需要保留大量数据 - 大型BLOB或类似数据 - 否则应使用NSUserDefaults

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

如果需要在启动之间保留大量状态,那么归档/取消归档肯定可以正常工作。但是,你将档案与终止联系起来;你是否真的希望用户在强行退出,放弃或设备重新启动时丢失数据(很多用户都有不自然的迷信)?