0

我无法弄清楚如何让存档在 iOS 5 应用程序中工作。我有一个单例 SessionStore,如果它在初始化时存在,我想检索它。SessionStore 继承自 NSObject 并有一个 ivar,一个 NSMutableArray *allSessions,我想从 plist 文件中加载它。这是 SessionStore.m 不确定问题是否明显或者您是否需要更多信息......谢谢!弥敦道

#import "SessionStore.h"

static SessionStore *defaultStore = nil;

@implementation SessionStore

+(SessionStore *)defaultStore {
    if (!defaultStore) {
        // Load data.plist if it exists
        NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    if ([fileManager fileExistsAtPath:pathInDocuments])
        defaultStore = [NSKeyedUnarchiver unarchiveObjectWithFile:pathInDocuments];   
    } else
        defaultStore = [[super allocWithZone:NULL] init]; 

    return defaultStore;
}


+(id)allocWithZone:(NSZone *)zone {
    return [self defaultStore];
}

-(id)init {
    if (defaultStore)
        return defaultStore;

    self = [super init];

    if (self)
        allSessions = [[NSMutableArray alloc] init];

    return self;
}

-(NSMutableArray *)allSessions {
    if (!allSessions) allSessions = [[NSMutableArray alloc] init];
    return allSessions;
}

-(void)setAllSessions:(NSMutableArray *)sessions {
    allSessions = sessions;
}

-(void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:allSessions forKey:@"All Sessions"];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [SessionStore defaultStore];
    [self setAllSessions:[aDecoder decodeObjectForKey:@"All Sessions"]];
    return self;
}

在 AppDelegate.m 中,它在终止时保存 plist 文件:

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Save data to plist file
    NSString *pathInDocuments = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"data.plist"];

    [NSKeyedArchiver archiveRootObject:[SessionStore defaultStore] toFile:pathInDocuments];
}
4

1 回答 1

0

我通常这样做的方法是拥有一个数据文件,我在需要时将其保存到,然后在初始化对象时将它们重新加载。所以是这样的:

@interface SessionStore
@property (nonatomic, copy) NSMutableArray *allSessions;

- (void)loadData;
- (void)saveData;
@end

static SessionStore *sharedInstance = nil;

static NSString *const kDataFilename = @"data.plist";

@implementation SessionStore

@synthesize allSessions = _allSessions;

#pragma mark -

+ (id)sharedInstance {
    if (sharedInstance == nil)
        sharedInstance = [[self alloc] init];
    return sharedInstance;
}


#pragma mark -

- (id)init {
    if ((self = [super init])) {
        [self loadData];
    }
    return self;
}


#pragma mark -

- (void)loadData {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:kDataFilename];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path]) {
        NSMutableData *theData = [NSData dataWithContentsOfFile:path];
        NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
        self.allSessions = [[decoder decodeObjectForKey:@"allSessions"] mutableCopy];
        [decoder finishDecoding];
    }

    if (!_allSessions) {
        self.allSessions = [[NSMutableArray alloc] initWithCapacity:0];
    }
}

- (void)saveData {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:kDataFilename];

    NSMutableData *theData = [NSMutableData data];
    NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];

    [encoder encodeObject:_allSessions forKey:@"allSessions"];
    [encoder finishEncoding];

    [theData writeToFile:path atomically:YES];
}

Then whenever I want to, I would call saveData to save the data back to disk. That might be every time allSessions changes, or just once when the app terminates / goes into the background. That would depend on how often allSessions changes and how crucial it is to ensure the data is saved.

Please bear in mind that the code there for the singleton is by no means the best - search around here on StackOverflow for reasoning behind using GCD dispatch_once or similar if you're worried about sharedInstance being racey.

I think this is better than your method because you are trying to serialise the whole singleton object rather than just its contents which I think is a bit easier to understand what's going on and then the singleton itself handles all the loading and saving rather than having your NSKeyedArchiver spill out into the app delegate like you have done.

于 2012-02-06T19:04:50.097 回答