Reputation: 33146
There are many questions on this already, but the answers given are situation-specific, answering the poster's personal problem rather than the question title.
I would like to know if there is a general, universal, easy way to convert an NSString
to an NSDictionary
, and vice versa?
I've got difficult/complex/non-cross-platform approaches, but surely there must be an easier way?
Here's what I know / have tested:
Dictionary
-> String
method that has no inverse, and works perfectly so long as your Dictionary is only basic datatypes, arrays, and dictionaries. This covers most real-world cases, but Apple doesn't give an inverse :(.
[myDictionary description];
NSData
that fails silently, so that it only works in a LIMITED set of real-world cases:
[myString dataUsingEncoding:NSUTF8StringEncoding];
[[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
// NB: silently fails in many cases, returns nil stringNSDictionary
-> NSData
-> NSDicitonary
that work well - but they are using NSData
, so they are not a straight conversion, and they are harder to work with
[NSKeyedArchiver archivedDataWithRootObject:myDictionary];
[NSKeyedUnarchiver unarchiveObjectWithData:myData];
[NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
[NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
[NSJSONSerialization JSONObjectWithData:myData options:0 error:nil];
[dataWithJSONObject:myDictionary options:0 error:nil];
As it stands, the only route that is GUARANTEED to work appears to be:
Write lots of code to output a verbose XML
or JSON
, converting it to NSData
, then converting back into NSString
, and send that on the wire.
Anything else has a slightly-less-than-100% success rate. Unfortunately, this technique turns a very common problem (string -> dictionary -> string) into a multiline chunk of silly boilerplate code we shouldn't be writing.
Also ... the XML
-or-JSON
approach is the only one that correctly reports failures (if they occur) - both the encoding systems take NSError
pointers.
Upvotes: 5
Views: 11344
Reputation:
Apple provides a Dictionary -> String method that has no inverse
Huh? False. And no, you are not supposed to rely on description
. Use property lists instead.
Forwards:
NSData *plist = [NSPropertyListSerialization
dataWithPropertyList:theDict
format:NSPropertyListXMLFormat_v1_0
options:kNilOptions
error:NULL];
NSString *str = [[NSString alloc] initWithData:plist encoding:NSUTF8StringEncoding];
Backwards:
NSDictionary *dict = [NSPropertyListSerialization
propertyListWithData:[str dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions
format:NULL
error:NULL];
Sidenote:
and works perfectly so long as your Dictionary is only basic datatypes
those are called "property list objects".
Upvotes: 10
Reputation: 8546
What you want is:
id<nscoding> obj;
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:obj];
NSString * string = [data base64EncodedString];
And then the other way around
NSString * string;
NSData * data = [NSData dataFromBase64String:string];
id<nscoding> obj = [NSKeyedUnarchiver unarchiveObjectWithData:data]
You can add base64EncodedString and dataFromBase64String: with the NSData category available here NSData+Base64
NSUTF8StringEncoding return nil when you try to encode something that is not data made of an utf8 string.
Upvotes: 2