Reputation: 93
So, my app queries an Amazon Dynamo DB database and retrieves a few kilobytes worth of data. What I want the app to do is download everything the first time, and then every time after, just download a timestamp to see if it has the most recent version of the data. So that I only have to download the data every once in a while, I'm trying to use NSKeyedArchiver to archive the array that I'm downloading. I have tried this three different ways, and none of them work on an iPhone, although two of them work on the simulator.
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:@"dataArray.archive"];
This does not work on the simulator nor the actual iphone. The result of this method is NO.
The next thing I used was the full path:
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:@"Users/Corey/Desktop/.../dataArray.archive"];
And this worked on the simulator, but not on the iPhone. My guess was that when compiled, the filesystem looks different (and obviously doesn't have the same path). So next I tried:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"dataArray" ofType:@".archive"];
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:filePath];
Once again, this works on the simulator but fails on the iphone. I have confirmed that all of the data is in self.dataArray before writing to the archive, and confirmed that the array is nil after writing back to the archive (in the iphone version). Any ideas what's going on? Is there a better way to do the filepath?
Upvotes: 0
Views: 1182
Reputation: 93
This is what I tracked down:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent: @"dataArray.archive"];
[NSKeyedArchiver archiveRootObject:your_object toFile:filePath];
and it worked perfectly on both the simulator and the iPhone!
Upvotes: 1
Reputation: 33389
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:@"dataArray.archive"];
You have to provide a full path.
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:@"Users/Corey/Desktop/.../dataArray.archive"];
That is not a full path. A full path begins with /
and does not have /../
anywhere.
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"dataArray" ofType:@".archive"];
You do not have permission to write inside the mainBundle, it is read only.
Also, in general you shouldn't use file paths, you should use URLs. Some APIs (including this one) requires a path but URLs are the recommended approach these days.
Here's the proper way to write the file to disk:
NSURL *applicationSupportUrl = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask][0];
applicationSupportUrl = [applicationSupportUrl URLByAppendingPathComponent:@"My App"]; // replace with your app name
if (![applicationSupportUrl checkResourceIsReachableAndReturnError:NULL]) {
[[NSFileManager defaultManager] createDirectoryAtURL:applicationSupportUrl withIntermediateDirectories:YES attributes:@{} error:NULL];
}
NSURL *archiveUrl = [applicationSupportUrl URLByAppendingPathComponent:@"foo.archive"];
[NSKeyedArchiver archiveRootObject:self.dataArray toFile:archiveUrl.path];
Upvotes: 0