Question

I am trying to save two strings. One string needs to be saved as type ARRAY in the pList and the second string needs to be saved as String in the Array.

I can use the code:

[dictionary setObject:(id)anObject forKey:(id)aKey>]

but it doesn't save it correctly. I can cast one of the strings as an array, but it still doesn't work right.

What is the proper method for saving an array to the pList?

Here is what my pList looks like:

<dict>
<key>Test One</key>
<array>
    <string>A13#</string>
</array>
<key>Another Test</key>
<array>
    <string>1111111111</string>
</array>
<key>Test Three</key>
<array>
    <string>2222222222</string>
</array>
<key>Final Test</key>
<array>
    <string>3333333333</string>
</array>
</dict>

here is the method I am using to try to

-(void)writeToFile:(NSString *)s1{
    NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:@"saved" ofType:@"plist"];

NSMutableDictionary *dictionary = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] mutableCopy];
NSString *tempString = [NSString stringWithFormat:@"1234567"];
[dictionary setObject:tempString forKey:s1];

[dictionary writeToFile:plistPath atomically:YES];
}
Was it helpful?

Solution

You can't cast or otherwise convert a string into an array; they're separate, distinct objects. It's the same as if in real life you try to turn your dog into a station wagon, it isn't happening.

Instead, put your dog inside the station wagon (or put your string(s) inside an array). You can create the array with [NSArray arrayWithObjects:@"string1", @"string2", nil];. Stick that inside your dictionary for a given key, along with your final string for another key, save it, and you'll have a plist with an array of one or more strings.

Also, in your code example your dictionary is leaking memory. Read up on memory management in Objective-C, you're going to run into lots of crashes and performance issues until you understand it well.

OTHER TIPS

You an convert a string to a single element array with

[NSArray arrayWithObject:str];

So if you want your plist to contain entries as arrays of strings, and you want just a single string as an element, then you do something like:

[dictionary setObject:[NSArray arrayWithObject:tempString] forKey:s1];

I don't actually no why you would want it this way unless you want to allow for multiple strings per key at some other time.

Also, as Marc mentioned, you are leaking the initial (unmutable) dectionary you create. Read the memory management rules at http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html.

Further, you should never write inside your application's bundle. For one thing, your application may be on a write protected volume or the current user may not have permissions to change it. For another, the file would then be shared by all users. And for a third, it would break the code signing. Instead, write the file to either the Preferences folder or the Application Support folder.

And finally, if these are intended to be user preferences of some sort, then you should use the preferences system, which allows configuring defaults and stores the preferences in the preferences folder for you. See http://developer.apple.com/documentation/Cocoa/Conceptual/UserDefaults/UserDefaults.html for more information.

The correct way to save an NSArray (by itself) to a plist file is as follows:

NSArray* anArray = ...;
[anArray writeToFile:@"/path/to/file.plist" atomically:YES];

However, you can't save an NSString as an array. Given the XML plist you provided, if you want to add entries with the same format, you can use this much simpler code:

- (void) writeToFile:(NSString *)string {
  NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"saved" ofType:@"plist"];
  NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
  [dictionary setObject:[NSArray arrayWithObject:@"1234567"] forKey:string];
  [dictionary writeToFile:plistPath atomically:YES];
}

This also avoids a memory leak in your code, where the receiver of -mutableCopy escapes with a retain count of 1. (This isn't a problem under GC, but it's still bad practice.) You shouldn't need to use +[NSString stringWithFormat:], just use a string literal. If you want to use a different as the string in the array, you can either pass it in as an additional parameter, grab it from another method, etc.

This method is still brittle in that it only stores one string in the array matched with the given key — also, the method name would be better if it were more indicative of exactly what it does. Also, if there will only ever be one string value for each key, you might consider revising the plist to omit the arrays entirely, since it just chews up space and complicates the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top