Parse Plist (NSString) into NSDictionary
Asked Answered
C

3

26

So I have a plist structured string, that get dynamically (not from the file system). How would I convert this string to a NSDictionary.

I've tried converting it NSData and then to a NSDictionary with NSPropertyListSerialization, but it returns "[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x100539f40" when I attempt to access the NSDictionary, showing that my Dictionary was not successfully created.

Example of the NSString (that is the plist data):

<?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>Key1</key> 
 <dict> 
  <key>Test1</key> 
  <false/> 
  <key>Key2</key> 
  <string>Value2</string> 
  <key>Key3</key> 
  <string>value3</string> 
 </dict> 
</dict> 
</plist> 

Thanks!

Conjoin answered 2/7, 2009 at 3:24 Comment(0)
N
75

See Serializing a Property List (web.archive.org link)

NSData* plistData = [source dataUsingEncoding:NSUTF8StringEncoding];
NSString *error;
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
NSLog( @"plist is %@", plist );
if(!plist){
    NSLog(@"Error: %@",error);
    [error release];
}
Newcastle answered 2/7, 2009 at 3:44 Comment(13)
+1 Your solution seems nicely polished — using immutable for creating an NSDictionary and remembering to release the error if there is one are worth bonus points. :-)Downhill
I almost called that an over-release. Um, wow. That API totally violates the memory management rules by requiring the caller to release that error string.Sperling
According to the Release Notes, it changed to not have that violation in Leopard. Worth looking out for. There's a bug report about it: openradar.appspot.com/5563963Sperling
My understanding is that the documentation is correct and the release notes are (now) wrong, as Apple decided to leave the leak in for compatibility reasons.Saire
Michael Tsai: so you’re saying that my code that crashed on 10.5.0 when built against the Leopard SDK, because it was following the documented behaviour, will now leak on current versions of Leopard, unless I do a version check against an unspecified/undocumented version of the OS? [Citation needed]Brian
The memory management rules only really talk about the return value, not asside values returned via reference like this, which, weirdly, do typically require releasing.Newcastle
Ahruman: I'm saying that your code will now leak, but you don't need to do a version check because only pre-release versions of 10.5 released the error string for you. Read the "NSPropertyListSerialization (Updated since WWDC 2007)" section of the updated release notes: developer.apple.com/releasenotes/Cocoa/Foundation.htmlSaire
Hmm, that is interesting. I saw what appeared to be the changed behaviour in 10.5.0 final, and it went away when I stopped releasing the string. I wonder what my real bug was…Brian
This method is now deprecated and you should use propertyListWithData:options:format:error: instead.Wend
please add swift version.Prettify
Sorry, I don't know a lick of Swift I'm afraid. If someone else wants to edit it to add a Swift variant, that's fine with me.Newcastle
Please review your answer - your link to "Serializing a Property List" is broken and leads nowhere. Maybe it's better to replace it (or add) decent search-string in Apple's documentation site for the correct thing?Abra
Sadly, Apple and documentation are a problematic mix. I have adjusted the link to the WaBack Machine archive of the article.Newcastle
O
13

Try this:

NSData * data = [yourString dataUsingEncoding:NSUTF8StringEncoding];

NSString *errorDesc = nil;
NSPropertyListFormat format;
NSDictionary * dict = (NSDictionary*)[NSPropertyListSerialization
                                      propertyListFromData:data
                                      mutabilityOption:NSPropertyListMutableContainersAndLeaves
                                      format:&format
                                      errorDescription:&errorDesc];
Odonnell answered 2/7, 2009 at 3:36 Comment(2)
Except for the memory leak, but heck it happens (:Stanford
NSDictionary * dict = (NSDictionary*)[NSPropertyListSerialization ...... You need to check the file you are trying to read as you may be returning an NSArray instead of NSDictionary.Fustanella
S
1

I've tried converting it NSData and then to a NSDictionary with NSPropertyListSerialization, but it returns "[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x100539f40" when I attempt to access the NSDictionary, showing that my Dictionary was not successfully created.

No, it shows no such thing. What it shows is that you tried to treat a string as an array. You'd need to determine where in the plist you were trying to get an array and why there was a string where you expected an array—i.e., whether you created the plist incorrectly (putting a string into it where you meant to put an array) or are examining it incorrectly (the presence of a string is correct; your subsequent expectation of an array is wrong).

Sperling answered 20/1, 2012 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.