If I want to store 2 strings, and ABContact image (or a variable to call the image) that persist even after restarting the application, which method should I use? NsMutableArray, plist or SQLite?
An NSMutableArray
will not persist after the application is restarted.
You may want to look at a plist that stores the two strings and a file URL pointing to the address book image that is cached in the application's Documents sandbox.
If you have lots of these to store and retrieve between application restarts, look into Core Data.
For very small amounts of data, like a few strings, but not an image, you could also use the much simpler NSUserDefaults. This is usually for saving preferences or some persistent data.
To save it:
[[NSUserDefaults standardUserDefaults] aString forKey:@"aStringKey];
if (![[NSUserDefaults standardUserDefaults] synchronize])
NSLog(@"not successful in writing the default prefs");
To read it:
aString = [[NSUserDefaults standardUserDefaults] stringForKey:@"aStringKey];
Again, I wouldn't go ahead and use this if what you really need is a database or a filesystem.
If you are putting in more data, and not enough to warrant an SQL database or Core Data, then I would write the data to a plist file. If all your data are objects, then I would do this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:kSavedDocFileName];
NSMutableArray *myArrayToSave = [[NSMutableArray alloc] arrayWithCapacity: 48];
// 48 since you said in the comments that you have 48 of these
for (int i = 0; i < 48; i++) {
NSDictionary *myDict = [[NSDictionary alloc] initWithObjectsAndKeys:
sting1[i], @"firstStr", //I'm assuming your strings are in a C array.
string2[i], @"secondStr",// up to you to replace these with the right
url[i], @"myURL", //way to access your 48 pieces of data
nil];
[myArrayToSave addObject:myDict];
[myDict release];
}
if (![myArrayToSave writeToFile:path atomically:YES])
NSLog(@"not successful in saving the unfinished game");
And you can read the data:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:kMySavedDocName];
NSArray *myLoadedData = [[NSArray alloc] initWithContentsOfFile:path];
for (int i = 0; i < 48; i++) {
NSDictionary *myDict = [myLoadedData objectAtIndex:i];
string1[i] = [myDict objectForKey:@"firstStr"];
string2[i] = [myDict objectForKey:@"secondStr"];
url[i] = [myDict objectForKey:@"url"];
}
[myLoadedData release];
Make sure you don't just copy and paste this code since I just typed it in off the top of my head.
Now, if you don't want to mess with a dictionary, you could do that too. It's a little less elegant:
Save:
NSMutableArray *myArrayToSave = [[NSMutableArray alloc] arrayWithCapacity: 48 * 3];
// 48 since you said in the comments that you have 48 of these three objects
for (int i = 0; i < 48; i++) {
[myArrayToSave addObject:string1[i]];
[myArrayToSave addObject:string2[i]];
[myArrayToSave addObject:url[i]];
}
if (![myArrayToSave writeToFile:path atomically:YES])
NSLog(@"not successful in saving the unfinished game");
Load:
NSArray *myLoadedData = [[NSArray alloc] initWithContentsOfFile:path];
for (int i = 0; i < 48; i++) {
string1[i] = [myLoadedData objectAtIndex:i * 3];
string2[i] = [myLoadedData objectAtIndex:i * 3 + 1];
url[i] = [myLoadedData objectAtIndex:i * 3 + 2];
}
[myLoadedData release];
Another important note is that in all these examples, I am assuming that you are dealing with objects (48 times 3 of them). That is why you can just add them to dictionaries and arrays and save them and reload them easily. If you were dealing with non-objects, like ints, or c strings or BOOLs, then you will have to use [NSNumber ...] to turn those into objects and then [object ...] to turn them back into non-ojects to begin with.
Try some of these, and then go find your app folder in ~/Library/Application Support/iPhone Simulator/Applications folder, and look in the Documents folder, open the file you have saved, and verify its contents. It's always reassuring to be able to check the data you write out - and to see how the different methods change the contents.
Good luck!
Don't do a database. It's way overkill for that little data. A plist would be fine. You should probably not use NSUserDefaults, I think that's right on the borderline of too much data for it. Just write a plist to the documents directory inside your application, and load it up when your application restarts. You can store an NSMutableArray in a plist, but it comes back to you as an NSArray. Just re-create it as a mutable array with [NSMutableArray arrayWithArray:] and retain it.
Hi mahbudz,
- (void)doneAceSpadeSetupClick:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *string1;
NSString *string2;
NSString *string3;
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"card1.plist"];
NSMutableArray *myArrayToSave = [[NSMutableArray alloc] initWithCapacity: 1];
//48 since you said in the comments that you have 48 of these
NSDictionary *myDict = [[NSDictionary alloc] initWithObjectsAndKeys:
string1, characterText.text, //I'm assuming your strings are in a C array.
string2, actionText.text,// up to you to replace these with the right
string3, objectText.text,
nil]; //iPhone simulator crashed at this line
[myArrayToSave addObject:myDict];
if (![myDict writeToFile:path atomically:YES])
NSLog(@"not successful in saving the unfinished game");
[self dismissModalViewControllerAnimated: YES];
}