Pergunta

Ok, I've been over this a million times in the last week and I just am not getting it. (And yes, I've read Apple's docs.)

I am archiving my object and it appears to be archiving correctly (I can see the file written to the file system and if I examine it I can see my data within). However, when I relaunch my app my data is not being restored. Every example I read tells me how easy this is but I'm just not getting it. One unique thing is that my object is a singleton, it's used for passing data between view controllers.

I'd really appreciate some sage advice. Thanks in advance.

Here's my header:

#import <Foundation/Foundation.h>

@interface SharedAppDataObject : NSObject <NSCoding>
{
    NSMutableDictionary *apiKeyDictionary;
    NSString *skuFieldText;
    NSIndexPath *checkmarkIndex;
}

+ (SharedAppDataObject *)sharedStore;

@property (nonatomic, copy) NSString *skuFieldText;
@property (nonatomic, copy) NSIndexPath *checkmarkIndex;
@property (nonatomic, copy) NSMutableDictionary *apiKeyDictionary;

-(void)setValue:(NSString *)apiKey forKey:(NSString *)name;

-(void)setSkuField:(NSString *)s;
-(void)setCheckmarkIndex:(NSIndexPath *)p;

-(NSMutableDictionary *)apiKeyDictionary;
-(BOOL)saveChanges;

@end

Here's my implementation:

#import "SharedAppDataObject.h"

@implementation SharedAppDataObject

@synthesize skuFieldText;
@synthesize checkmarkIndex;
@synthesize apiKeyDictionary;


    //create our shared singleton store
+(SharedAppDataObject *)sharedStore {

    static SharedAppDataObject *sharedStore = nil;

    if (!sharedStore) {
        sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];

        if(!sharedStore) 
            sharedStore = [[super allocWithZone:NULL] init];
    }
    return sharedStore;
}

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

-(void)setValue:(id)apiKey forKey:(NSString *)name {
        [apiKeyDictionary setObject:apiKey forKey:name];
}

-(void)setSkuField:(NSString *)s {
    skuFieldText = s;
}

-(NSMutableDictionary *)apiKeyDictionary {  
    return apiKeyDictionary;
}

-(void)setCheckmarkIndex:(NSIndexPath *)p {
    checkmarkIndex = p;   
}

-(void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:skuFieldText forKey:@"skuFieldText"];
    [aCoder encodeObject:checkmarkIndex forKey:@"checkmarkIndex"];
    [aCoder encodeObject:apiKeyDictionary forKey:@"apiKeyDictionary"];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        [self setSkuFieldText:[aDecoder decodeObjectForKey:@"skuFieldText"]];
        [self setCheckmarkIndex:[aDecoder decodeObjectForKey:@"checkmarkIndex"]];
        [self setApiKeyDictionary:[aDecoder decodeObjectForKey:@"apiKeyDictionary"]];
    }
    return self;
}

+(NSString *)archivePath {
    NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [documentDirectories objectAtIndex:0];
    return [documentDirectory stringByAppendingPathComponent:@"bbyo.archive"];
}

-(BOOL)saveChanges {      
    return [NSKeyedArchiver archiveRootObject:self toFile:[SharedAppDataObject archivePath]];  
}

@end

Save method from App Delegate:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    BOOL success = [[SharedAppDataObject sharedStore] saveChanges];

    if (success) {
        NSLog(@"Saved all the data");
    } else {
        NSLog(@"Didn't save any of the data");
    }
}
Foi útil?

Solução

Initialize sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]]; in application:didFinishLaunchingWithOptions:. This method is used to initialize data structures and restore previous app state.

Also, take out static SharedAppDataObject *sharedStore = nil; from sharedStore. If the save file exists, [ShareAppDataObject sharedStore] will always unarchive the file which is not necessary. It can be unarchived once during initialization.

Here's a post that can answer your problem: http://bit.ly/PJO8fM

Outras dicas

I cannot give you the answer but some ideas to figure this out. Taking this line:

sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];

So if the sharedStore is nil, something is wrong - so test for it. If nothing then log the path, and use NSFileManager methods to see if the file is there, its size etc. If you find the file is there and has size, but you cannot unarchive it, that's a problem of course. In that case, add special debug code just after you create the file:

-(BOOL)saveChanges {      
    BOO ret =  [NSKeyedArchiver archiveRootObject:self toFile:[SharedAppDataObject archivePath]];
    id foo = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];
    // check if foo is not nil, if its the proper class, etc.
}

If when you save the file you can unarchive it just fine, but cannot on restart of the app, then something is wrong with the file. All this info should point the way to a solution.

Another thought - when you encode the data, log it, just to be sure its not nil - but even if so the unarchive should work.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top