Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS: Save Array when app is close or enter background

I have a cartArray(in AppDelegate.h @interface above) that need to be saved when the app in background mode or the app closed. The app worked fine when the cartArray has nothing but crashed when I added an item (Cart) in it and entered the background or closed the application by pressing the minus sign. My cartArray contains cart class in it. May I know what is happening? The tutorial online is so complicated and I always find myself lost in the middle of explanation.

[AppDelegate.m]

- (void)applicationDidEnterBackground:(UIApplication *)application {
[AppDelegate saveData]; 
}

- (void)applicationWillEnterForeground:(UIApplication *)application {   
[AppDelegate getData];   
}

+(NSString *) getPathToAchieve{  NSLog(@"+++++getPathToAchieve");
    static NSString* docsDir = nil;
    if (docsDir == nil) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        docsDir = [paths objectAtIndex:0];
    }
    NSString *fullFileName = [NSString stringWithFormat:@"%@.plist", docsDir];
    return fullFileName;
}

- (void)applicationWillTerminate:(NSNotification *)notification{    
    [cartArray writeToFile:[AppDelegate getPathToAchieve] atomically:YES];
}

-(id)initWithCoder:(NSCoder *)aDecoder
{   self = [super init];
   if (self != nil)
   {
        cartArray = [aDecoder decodeObjectForKey:@"cartArrayKeys"];
   }
    return self;  
}

-(void)encodeWithCoder:(NSCoder *)anEncoder
{   
    [anEncoder encodeObject:cartArray forKey:@"cartArrayKeys"];
}

+(void)saveData{ 
     [NSKeyedArchiver archiveRootObject:cartArray toFile:[self getPathToAchieve] ];
}

+(id)getData{ 
    return [NSKeyedUnarchiver unarchiveObjectWithFile:[self getPathToAchieve]];
}
like image 277
shoujo_sm Avatar asked Nov 01 '22 15:11

shoujo_sm


2 Answers

Your code is pretty messy. First, implement -(id)initWithCoder: and -(void)encodeWithCoder: in your Cart class, not AppDelegate class (and make sure Cart conforms to NSCoding protocol):

- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.title forKey:@"title"];
    [encoder encodeObject:self.description forKey:@"description"];
    .....
}

- (id)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        self.title = [decoder decodeObjectForKey:@"title"] ;
        self.description = [decoder decodeObjectForKey:@"description"] ;
        ....
    }
    return self;
}   

Second, implement -(void)saveData and -(void)getData:

-(void)saveData{ 
     [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:cartArray] forKey:@"cartArray"];
}

-(void)getData{ 
    NSData *savedArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"cartArray"];
    if (savedArray != nil)
    {
        NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:savedArray];
        if (oldArray != nil) {
            cartArray = [[NSMutableArray alloc] initWithArray:oldArray];
        } else {
            cartArray = [[NSMutableArray alloc] init];
        }
    }
}

Call saveData when application is going to be terminated / entered background. Call getData when application has loaded.

like image 118
Andrey Gordeev Avatar answered Nov 10 '22 21:11

Andrey Gordeev


do all your saving in

- (void)applicationWillResignActive:(UIApplication *)application

from the documentation:

Tells the delegate that the application is about to become inactive. This method is called to let your application know that it is about to move from the active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. An application in the inactive state continues to run but does not dispatch incoming events to responders. You should use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. An application in the inactive state should do minimal work while it waits to transition to either the active or background state.

like image 40
RTasche Avatar answered Nov 10 '22 20:11

RTasche