Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-08-2010, 12:46 PM   #1 (permalink)
Registered Member
 
Join Date: Jul 2009
Posts: 50
o2fill is on a distinguished road
Default Persistency pandemonium

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.
o2fill is offline   Reply With Quote
Old 09-08-2010, 01:10 PM   #2 (permalink)
Registered Member
 
lukeinjax's Avatar
 
Join Date: May 2010
Posts: 125
lukeinjax is on a distinguished road
Default

This should give you a good start:

Storing custom objects in an NSMutableArray in NSUserDefaults - Stack Overflow

Basically, your custom objects need to conform to the NSCoding protocol:

NSCoding Protocol Reference
lukeinjax is offline   Reply With Quote
Old 09-08-2010, 03:24 PM   #3 (permalink)
Registered Member
 
Join Date: Jul 2009
Posts: 50
o2fill is on a distinguished road
Default Thanks and a follow up

Quote:
Originally Posted by lukeinjax View Post
This should give you a good start:

Storing custom objects in an NSMutableArray in NSUserDefaults - Stack Overflow

Basically, your custom objects need to conform to the NSCoding protocol:

NSCoding Protocol Reference
Thanks. I got the first part but I'm still struggling with the second part. So, does this mean that I need to create a subclass of NSArray, for each array I wish to encode, that implements the NSCoding protocol?
o2fill is offline   Reply With Quote
Old 09-08-2010, 03:34 PM   #4 (permalink)
Registered Member
 
lukeinjax's Avatar
 
Join Date: May 2010
Posts: 125
lukeinjax is on a distinguished road
Default

Quote:
Originally Posted by o2fill View Post
Thanks. I got the first part but I'm still struggling with the second part. So, does this mean that I need to create a subclass of NSArray, for each array I wish to encode, that implements the NSCoding protocol?
NSArray already conforms to NSCoding, so no need to subclass NSArray.

In order to save the custom objects contained within the array, those objects need to implement the NSCoding protocol including the required methods (initWithCoder and encodeWithCoder).
lukeinjax is offline   Reply With Quote
Reply

Bookmarks

Tags
file, nsuserdefaults, save

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 332
11 members and 321 guests
bignoggins, carlandrews, flamingliquid, hzwegjxg, ilmman, jenniead38, linkmx, nadav@webtview.com, stanny, v1n2e7t
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,657
Threads: 94,116
Posts: 402,889
Top Poster: BrianSlick (7,990)
Welcome to our newest member, jenniead38
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 11:50 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0