I have an app that uses three arrays to hold some basic game data. Two of the arrays are arrays of button objects. One array holds custom "cell" objects [sublcass of NSObject]. What I want to do is to save the contents of the arrays in some fashion so that, if the game is interrupted, I can restore the game to its latest state.
I have tried two ways of doing this. The first approach is to use the [NSMutableArray writeToFile: @"afile" atomically: YES] and then restore the data using [NSMutableArray initWithContentsOfFile:@"afile"]. This approach does not work as it appears that, at least in the simulator environment, nothing is being saved or recovered (but no errors either) Here's my code:
Code:
//save the arrays
- (void) saveCriticalFiles {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSString *filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"cells.plist"]];
[cells writeToFile:filePath atomically:YES];
filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"board.plist"]];
[[boardView subviews] writeToFile:filePath atomically:YES];
filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"keys.plist"]];
[[keyView subviews] writeToFile:filePath atomically:YES];
[filePath release];
}
// and here's how I try to recover the data.
....NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSString *filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"cells.plist"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
showHints = [defaults boolForKey:@"hints"];
if (![fileManager fileExistsAtPath:filePath]){
[self setUpGame];
}
else {
cells = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"board.plist"]];
NSArray *buttonArray = [[NSArray alloc] initWithContentsOfFile:filePath];
for (UIButton *b in buttonArray) {
[boardView addSubview:b];
}
[buttonArray release];
filePath = [[NSString alloc] initWithString:[dir stringByAppendingPathComponent:@"keys.plist"]];
NSArray *keyArray = [[NSArray alloc] initWithContentsOfFile:filePath];
for (UIButton *b in keyArray) {
[keyView addSubview:b];
}
[keyArray release];
[self checkKeys];
if([self checkGame]) [self gameCompleted];
}
The other approach I tried was to save the arrays in the app defaults. I am using this approach successfully to save some other, simpler (BOOL) data. However, when I try to do it with more complex objects I'm running into issues. Here's the code:
(Note: I set up the NSUserDefaults object "defaults" during init and use it when needed throughout the app)
Code:
//saving
[defaults setObject:cells forKey:@"cells"];
[defaults setObject:[boardView subviews] forKey:@"buttons"];
[defaults setObject:[keyView subviews] forKey:@"keys"];
//recovering
... if ([defaults objectForKey:@"cells"] != nil) {
//clear all of the buttons from their superViews
for (UIButton *button in boardView.subviews) {
[button removeFromSuperview];
}
for (UIButton *button in keyView.subviews) {
[button removeFromSuperview];
}
cells = [defaults objectForKey:@"cells"];
NSMutableArray *buttonArray = [defaults objectForKey:@"buttons"];
for (UIButton *b in buttonArray) {
[boardView addSubview:b];
}
[buttonArray release];
NSMutableArray *keyArray = [defaults objectForKey:@"keys"];
for (UIButton *b in keyArray) {
[keyView addSubview:b];
}
[keyArray release];
[self checkKeys];
if([self checkGame]) [self gameCompleted];
} else [self setUpGame]; ...
This approach is successfully recovering the data but to no effect as it causes some problems. Here's what I'm seeing in Console:
Code:
-[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
<UIRoundedRectButton: 0x3d35740; frame = (0 0; 25 25); opaque = NO; layer = <CALayer: 0x3d33e50>>,
...,
<UIRoundedRectButton: 0x3d38770; frame = (175 25; 25 25); opaque = NO; layer = <CALayer: 0x3d386f0>>
)' of class 'NSCFArray'
Is there a limitation on the types of objects that can be stored in this way?
Any suggestions on how to get either of these approaches working would be greatly appreciated.