Question

I am storing some dictionaries in plist files (iOS), which are subsequently encrypted. After reading the file contents and decrypting them I am returning the xml contents of the file in a string:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>password</key>
    <string>apassword</string>
    <key>username</key>
    <string>ausername</string>
</dict>
</plist>

I am aware of the methods: dictionaryWithContentsOfFile:(NSString *) and dictionaryWithContentsOfFile:(NSURL *) to create a dictionary from this type of data but am surprised there is no such dictionaryWithXML:(NSString *)

Short of writing this data to a file then reading it, something I was trying to avoid as it is just excessive, are there any obvious workarounds I'm missing?

Was it helpful?

Solution

NSPropertyListSerialization has a handy method that does it for you, reading from an NSData instance:

NSString *source = ... // The XML string

NSData* plistData = [source dataUsingEncoding:NSUTF8StringEncoding];

NSError *error;

NSMutableDictionary* plist = [NSPropertyListSerialization propertyListWithData:plistData
                                                                       options: NSPropertyListImmutable
                                                                        format:NULL
                                                                         error:&error];

As pointed out by @Adam in the comments, the dictionary returned by this method is always mutable. The options parameter serves to determine if the containers (arrays, dictionaries) held within the plist are also mutable or (the default) immutable.

If you want containers in the property list to also be mutable, you can use NSPropertyListMutableContainers - or NSPropertyListMutableContainersAndLeaves, if you need even the leaves to be mutable.

OTHER TIPS

As @Monolo stated in his answer, NSPropertyListSerialization is the way to go. However, you can get a NSMutableDictionary without copying the data to a new instance. Here is the code:

NSString *str = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd\"><plist version=\"1.0\"><dict><key>password</key><string>apassword</string><key>username</key><string>ausername</string></dict></plist>";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSPropertyListFormat format;
NSMutableDictionary *dict = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:&err];
if (err) {
    NSLog(@"err: %@", err);
}
NSLog(@"original dictionary: %@", dict);
[dict setValue:@"newPass" forKey:@"password"];
NSLog(@"modified dictionary: %@", dict);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top