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]];
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With