I'm currently building quite a large iPhone application. Bigger than I expected anyway. But that is beside the point, the overall idea of the application is to grab JSON from a web service, sort it all into custom NSObject's that are linked together and then present.
This goes all well and good. But, because I want the user to be able to see this information on the device without an internet connection, I need to save the information that I am presenting into the Documents folder that each Application has.
I basically implemented the NSCoding protocol into all the custom NSObject's that would need it in order to save it into a subdirectory of the Documents directory.
This is all achieved through this function here.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataFileString]) //Does directory already exist?
{
MACompany *company = [MACompany sharedMACompany];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) //Does directory already exist?
{
if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath
withIntermediateDirectories:NO
attributes:nil
error:&error])
{
NSLog(@"Create directory error: %@", error);
}
}
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:company forKey:@"MACompany"];
[archiver finishEncoding];
[[NSFileManager defaultManager] createFileAtPath:dataFileString
contents:data
attributes:nil];
[archiver release];
[data release];
} else {
NSLog(@"File already exists, no need to recreate, not yet anyway");
}
}
I do the following request when the user first loads the application (application didFinishLaunchingWithOptions:
) and when the user opens the application after being in the background (applicationWillEnterForeground:
).
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataFileString]) //Does directory already exist?
{
NSLog(@"Create a new Company Request");
MAWebRequests *companyReq = [[MAWebRequests alloc] init];
[companyReq getCompanyDetails];
[companyReq release];
} else {
NSLog(@"Saved Company Needs to be Decoded applicationWillEnterForeground");
MACompany *company = [MACompany sharedMACompany];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Data"];
NSString *dataFileString = [dataPath stringByAppendingPathComponent:@"Company.archive"];
NSData *data = [[NSData alloc] initWithContentsOfFile:dataFileString];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[data release];
company = [unarchiver decodeObjectForKey:@"MACompany"];
[unarchiver finishDecoding];
[unarchiver release];
}
Now this works all well and good and I can pull from this file also. But, I can only grab the data stored in this file when I have Xcode's debugger attached to the application. As soon as is stopped, the data is corrupted and doesn't include the original data.
The data is still stored there, I can see the created file, but the actual data itself that is stored within the file is wrong...
Should I not be using the above logic to save the data to the file and then pull recreate the shared object? Has anyone else tried to do such a thing and had success? Is there any reason as to why I'm running into this weird issue? Has anyone else had this issue?
Any help would be greatly appreciated, have been trying all sorts of different methods to get it to work and nothing has been able to get there. All I need to be able to do is be able to store the data there permanently until I need to update it...
I have resolved this issue by saving the MACompany object well before applicationDidEnterBackground:
Major thanks to @OleBegemann for his aid in finding where the issue nested.