Singleton archiving not unarchiving usable instance

时间:2015-04-29 00:28:38

标签: ios objective-c

I've run into some trouble trying to archive my singleton for my project. Technically this applies to two singletons that I archive under a single wrapper array but for the purposes of this question, I'll only involve the "Notebook" singleton.

My problem is that recalling this archive doesn't reproduce the instance correctly, everything appears to be "null" but the app otherwise performs.

My idea is to archive the singleton once the app enters the background, so here's that method in AppDelegate:

- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

Settings *sharedSettings = [Settings sharedSettings];
Notebook *sharedNotebook = [Notebook sharedNotebook];
NSArray *array_wrapperForSave = @[sharedSettings, sharedNotebook];

NSArray *archiveDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *archivePathForArray = [archiveDirectory objectAtIndex:0];
NSString *directoryForArray = [archivePathForArray stringByAppendingString:@"UserDataBundle.archive"];
archivePath = directoryForArray;

BOOL success = [NSKeyedArchiver archiveRootObject:array_wrapperForSave toFile:archivePath];

NSLog(@"Data Archive Status: %d", success);

That NSLog returns 1 (success)

Here is Notebook.m's initializer(s), the important offending line is that last method call:

#pragma mark - Initializers

- (instancetype)init {
    self = [super init];
    if (self) {
        array_highlights = [[NSMutableArray alloc] init];
        array_sections = [[NSMutableArray alloc] init];
        sharedSettings = [Settings sharedSettings];
        indexOfLastLoadedSection = 0;

        Section *rootSection = [[Section alloc] initWithTitle:@"Main Tab"];
        [self saveSection:rootSection];

//        self = [self accessArchivedInstance];     // This causes some huge issues.
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        array_sections = [aDecoder decodeObjectForKey:@"array_sections"];
        array_highlights = [aDecoder decodeObjectForKey:@"array_highlights"];
        indexOfLastLoadedSection = [aDecoder decodeIntegerForKey:@"indexOfLastLoadedSection"];
    }
    return self;
}

Here is that method which grabs the file path to the wrapper array and uncases the proper object instance at the index:

- (Notebook *)accessArchivedInstance {
    NSArray *archiveDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *archivePathForArray = [archiveDirectory objectAtIndex:0];
    NSString *directoryForArray = [archivePathForArray stringByAppendingString:@"UserDataBundle.archive"];


    NSArray *array_archivedSingletons = [NSKeyedUnarchiver unarchiveObjectWithFile:directoryForArray];
    Notebook *returnInstance = [array_archivedSingletons objectAtIndex:1];

    NSLog(@"Notebook Instance awaking from Archive");

    return returnInstance;
}

Singleton method:

+ (id)sharedNotebook {
    static Notebook *sharedNotebook = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedNotebook = [[self alloc] init];
    });

    return sharedNotebook;
}

I can of course provide any extra info if needed. Thanks in advance!

1 个答案:

答案 0 :(得分:2)

主要问题是你从未真正使用accessArchiveInstance,当你尝试它时,它位于错误的位置。

sharedNotebook修改为:

+ (id)sharedNotebook {
    static Notebook *sharedNotebook = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSArray *archiveDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *archivePathForArray = [archiveDirectory objectAtIndex:0];
        NSString *directoryForArray = [archivePathForArray stringByAppendingPathComponent:@"UserDataBundle.archive"];
        if ([[NSFileManager defaultManager] fileExistsAtPath:directoryForArray]) {
            NSArray *array_archivedSingletons = [NSKeyedUnarchiver unarchiveObjectWithFile:directoryForArray];
            sharedNotebook = [array_archivedSingletons objectAtIndex:1];
        } else {
            sharedNotebook = [[self alloc] init];
        }
    });

    return sharedNotebook;
}

并删除accessArchiveInstance方法。