I need to send a NSSet over the network, so I need to convert it to Data.
I have tried this:
let setData : Data = withUnsafeBytes(of: mySet) { Data($0) }
without success.
Convert to NSData is easy but what about Data?
How do I do that?
Either convert it to a general-purpose serialization form (JSON or binary Plist) using Codable (if it needs to be parsed by another system in a portable format), or hand it to NSKeyedArchiver using NSCoder (if it needs to be read just by Cocoa apps, and you want to save the "set-ness" and any object relationships).
Details on NSKeyedArchiver are in the Archives and Serializations Programming Guide.
Details on Codable are in Encoding, Decoding, and Serialization.
NSSet isn't Codable directly, but that doesn't matter because JSON and plists don't support sets anyway. You can just convert it to an Array (or Set).
Since you said that converting to NSData is easy, maybe you're already aware of all this, and all you need is Martin's comment: add as Data.
Related
i am currently in the middle of implementing the network side of my multi player game. So far i am sending classes across by serialising my objects into NSData. The trouble lies in the fact that i have link lists within my class referencing other objects of the same type. If i transferred all the objects across and decoded on the receiving end using initWithCoder: (NSCoder *) decoder would the objects within the class still hold the correct references? If not can anyone recommend a clean solution to this problem?
NSCoder should work fine for this. When you encode, encode the head of the list and use the list structure itself to guide the rest. Say the list has a string for it's data and a simple forward link. Just encode the head...
// in ListNode.m
- (void)encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:self.theString forKey:#"thisIsMyListsData"];
if (self.nextNode) {
[encoder encodeObject:self.nextNode forKey:#"nextNode"];
}
}
I want to serialize an object to an NSDictionary.
(key = value) will be (property-name = property-value)
If a property is another object, it will be recursively serialized as another NSDictionary inside the parent NSDictionary.
Does anyone have an idea? API? Pointer? Reflection? framework?
Thanks!
For what purpose do you need to turn an object into a dictionary?
If it is to save the object to a file, you should look at the NSCoder protocol, which you can implement for your object so that an array of your objects (for example) can be serialized by built in methods like NSArray's -writeToFile:atomically:.
Adopting NSCoding is certainly an option -- basically, your graph's elements would all need to know how to serialize/deserialize themselves (by adopting NSCoding). Under this approach, you would use the NSCoder interfaces for archiving and unarchiving.
Another common alternative would be a property list. This is a simpler more portable format with some restrictions to types. Namely, NSString, NSArray, NSDictionary, NSNumber (and CFBoolean), NSData, and NSDate - as well as their CoreFoundation counterparts. These types and collections all know how to serialize their elements appropriately. Here, you can use NSPropertyListSerialization for archiving and unarchiving. This is not much overhead for smaller tasks, but NSCoding is generally a better long term solution where portability is not a concern (e.g. export as XML) because the objects can maintain their serialization implementations without much intervention from the archiver.
For custom objects, you would typically support either a property list representation and/or NSCoding - but the collections types already know how to archive and unarchive themselves (provided of course their contents also support the approach to serialization you use).
More details can be found in Apple's 'Archives and Serializations Programming Guide'.
I have a Class for handling my data in my project, and now I need to store the data.
I'd like to use a Plist but I'm a bit unsure of how to start.
My class is pretty simple - 6 pieces of data, flat (no hierarchy).
I want my app to start with no data, so can I assume that I should create the PList programmatically once the User creates their first piece of data? (That is, don't create a .plist file in 'Supporting Files' prior to distribution?)
Then, when the app starts the next time, read the data and create an NSMUtableArray array of Class instances?
To create a property list, all you need to do is use appropriate types (i.e. those that support the property list format: NSData, NSString, NSDictionary, NSNumber, NSDate, NSArray), store them in a single container, and tell the containing object to write itself to a file. To read the data, you can initialize that same type using a path. For example:
// writing some data to a property list
NSString *somePath = ... // replace ... with the path where you want to store the plist file
NSMutableDictionary myDict = [NSMutableDictionary dictionary];
[myDict setObject:#"Caleb" forKey:#"name"];
[myDict setObject:[NSNumber numberWithInt:240] forKey:#"cholesterolOrIQ"];
[myDict writeToFile:somePath atomically:YES];
// reading the file again
NSDictionary *readDict = [NSDictionary dictionaryWithContentsOfFile:somePath];
The simplest way is to simple save an NSArray or NSDictionary to disk. Caleb's answer goes into detail there so I won't repeat it, other than to say you might have to convert a non-compatible object like NSColor to an property list object like NSData. It's up to you to do this each time you save or load your data.
NSKeyedArchiver and NSKeyedUnarchiver give you a little more control over the process, but work pretty much the same way. You provide (or get back) a plist compatible root object (usually an NSDictionary) that contains your data. I recommend creating a dictionary that includes your data structure as well as an arbitrary number (your app's build number is a good choice) to use as a version indicator. This way if you ever update your data model you can easily determine if you need to do anything to convert it to the new version.
If you're putting your own objects into the data file, look into NSCoding. The protocol gives you two methods using NSKeyedArchiver and NSKeyedUnarchiver to save and restore your data. This is by far the most straightforward approach if your data model consists of anything more than a few simple strings and numbers, since you're dealing with your own native objects. In your case, you would have your data class implement NSCoding and use the NSKeyedArchiver and NSKeyedUnarchiver methods to encode your six instance variables. When it's time to save or load, pack the instance of your class into an NSDictionary (along with a versioning number as I mentioned above) and call NSKeyedArchiver's archiveRootObject:toFile:. Your save an load methods deal only with your own data object, which makes things easy for you. The common pitfall to watch out for here is if your custom data object contains other custom object. This is fine, but you have to make sure every object that's going to be saved has its own NSCoding implementation.
Two things you can do:
Use NSUserDefaults:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
The objectForKey method is the one you want to use to store your class. But, as pointed out in the comments, this shouldn't really be used for storing lots of user data; it's best for saving preferences.
For storing more data, you might want to look at Core Data. It's more complex, but should be better suited to your needs. Here's a tutorial on it:
http://mobile.tutsplus.com/tutorials/iphone/iphone-core-data/
Neither of these seems best for your simple application, but I leave this answer up since it gives alternatives for saving data to the iPhone.
Conversion of NSMutableData to JSON or Dictionary in Objective C /iPhone App Program?
The NSMutableData that I get is the response from a webservice,
I can convert it easily to NSString, as there is a method - initWithBytes..
But I see the response to be (null).
Since the response actually is in JSON format, can I conver the NSMutableData into JSON using some method or including some framework. (The protocol for the webservice is written in SOAP)
Thanks in advance..
If you're getting your data as plain JSON in a coherent form, you can use this library on Github (JSONKit) to map your JSON strings to objects/dictionaries.
It's a very convenient and easy way to handle JSON. Advantages this library brings are listed on the Github page.
You can use the well-documented NSJSONSerialization class to do this. It comes with Foundation.
I feel a little dumbfounded. I know how to store any kind of "plist supporting" data in a preferences file, such as NSArray, NSDictionary, NSString and their CF counterparts. No problem there.
Now I like to store the values of my custom object this way. I had thought that if I implement some kind of serialization/archiving protocol, I could get NSUserDefaults to understand my class just like it understand NSDictionary.
E.g, implementing the NSCoding protocol should give the NSUserDefaults code all that it needs: I give it the key names along with the values as plist compatible types (NSString, mostly in my case). But my encoder doesn't even get invoked. :(
Then I thought that there must be at least some function that generates a NSDictionary from the NSCoding protocol, so that I can then send this dict to store in the prefs. Ideally, there'd by something like the NSKeyedArchiver that I pass any NSCoding compatible object and it gives me a NSDictionary, and vice versa. But that doesn't appeat to exist in Apple's framework.
Do I have to write that really myself? I'd expect this would be a quite common need.
Note: I realize that NSKeyedArchiver generates a binary plist, which I could write as a plist file. But that's not what I want. I want to add the contents of this object to my app's prefs plist file, i.e. I want to store both my object and other prefs data in the plist file. That's what doesn't seem to be possible with the given functions.
I'm currently just adding objects to an NSDictionary then calling NSDictionary's "writeToFile:atomically:" method. I'm mostly adding strings, and an image as NSData, but I believe anything I add to the NSDictionary that implements the NSCoding protocol should get written to the file.
Then later when I call NSDictionary's initWithContentsOfFile everything gets put back in the dictionary as it had been. Would this work for you - letting the dictionary take care of the serialization stuff?