How to serialize an object to an NSDictionary? - iphone

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'.

Related

How to use the CFMutableArrray

I am reading a video file using AVFoundation framework and getting the image buffers as CMSampleBuferRef, I added the buffers in CFMutableArrayRef using CFArrayAppendValue() function.
But If I want to retrieve from that array, Is there any way?
Apple document for CFMutableArrayRef gives no method to retrive from array.
You're looking for the CFArray function CFArrayGetValueAtIndex, or something similar. CFMutableArray's "inherit" from CFArrays, and the documentation on CFMutableArray only contains the API that differs from CFArray.
See the docs here.
In addition to using the APIs Matt pointed out (+1), CFMutableArray is toll-free-bridged with NSMutableArray. you can simply cast an instance of a CFMutableArray to an NSMutableArray and use NSMutableArray's methods (or the other way around). Following the cast to NSMutableArray, you can use -[NSArray objectAtIndex:].
Many Foundation types have CoreFoundation counterparts which are toll free bridged. As a toll free bridged type, the cast does not introduce a promotion or conversion. Think of them as the same type, and that instances may be converted/cast to their CF-NS counterparts without introducing overhead or change to the instance. Technically, implicit reference counting may be introduced if your implementation uses NS-types rather than CF-types under ARC.
This may be useful if you are writing in ObjC, and are more familiar with the ObjC APIs.

How to get good grip on NSMutableDictionary, NSEnumerator, NSMutableSet?

I am little bit backward in knowledge on these three topics: NSMutableDictionary, NSEnumerator, NSMutableSet. When I want to use them, it feels very hard, even when I've gone through the developer documentation.
Is there any sample code to understand it clearly for all three topics?
Please help me.
Thank you,
Madan Mohan.
The best way to understand these depends on what your prior experience is. NSDictionary is exactly what it sounds like: a dictionary. What that means is that given a key (or a headword, as in a dictionary), you can look up a value (or definition):
For instance, this dictionary gives information about my dog:
KEY VALUE
-------------------------------------------
#"name" #"tucker"
#"species" #"canis lupus familiaris"
#"favorite" #"biscuits"
With a dictionary dogInfo containing that information, we could send [dogInfo objectForKey:#"name"] and expect to receive #"tucker".
The difference between NSDictionary and NSMutableDictionary is that the latter allows changes after initialization. This lets you do things like [dogInfo setObject:#"fetch" forKey:#"game"]. This is helpful for maintaining state, memoizing referentially transparent requests, etc.
NSSet is a way to have a bunch of objects, with a few important bits: there is no defined order to those objects, and there can only be one of each object (no duplicates). Use NSSet for when you need to contain unique, unordered objects. NSMutableSet is the variant of NSSet which allows for changes (such as adding or removing objects) after initialization.
NSEnumerator is a bit more complicated, but you usually won't need to deal with it unless you are writing your own libraries, are coding archaically, or are doing complex enumerations. Subclasses of NSEnumerator are used by collection classes, such as NSDictionary, NSArray, and NSSet, to allow their objects to be enumerated. Usually, you'd just enumerate over them using a foreach-loop, since they all implement <NSFastEnumeration>. But sometimes, you'll want to do more specific things, like enumerate over the objects (instead of the keys) of a dictionary, or enumerate over an array in reverse. This is where instances of NSEnumerator (usually defined as properties on your collection objects) will become helpful.
Update
Justin in the comments pointed out that NSEnumerator conforms to <NSFastEnumeration>; that means, the chances are next-to-nothing that you'll need to know how to use an NSEnumerator; you can just do a foreach loop over the enumerator itself, like so:
for (id object in [dogDict objectEnumerator]) {
// doing something with the object, disregarding its key
}

OSX: How to store objects in plist file in an OO way

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?

Storing a C struct in CFMutableDictionary

Since there is no counterpart to NSValue in Core Foundation, how are we supposed to store C structs in a CFMutableDictionary?
First, you can put an NSvalue in a CFMutableDictionary as-is, so the answer is "use NSValue." But I assume the rest of your question is "without using any Cocoa objects." In that case, just create a non-retaining CFMutableDictionary, and you can put any pointer you want into it. See "Defining Custom Collection Callbacks" for some example code. I use these a lot.
Remember that these still have to be pointers, so you're going to have to allocate your structs on the heap, not the stack. And that means that memory management is now your problem. Of course you could create a custom set of callbacks that do whatever you want, so if you're using boost or something else with its own ref-counting system, you can still implement that with CFMutableDictionary.
And of course you can replace the struct with a small data object. That's usually a lot easier. But different problems need different solutions.
CFMutableDictionary
CFDictionaryAddValue
A CFType object or a pointer value to add to the dictionary.
you just pass a pointer to your struct.

Saving an NSMutableArray to Core Data

I want to add an NSMutableArray of NSStrings to one of my Entities in my core data model. The problem is that this isn't a supported type in Core Data.
I tried making a tranformable attribute, but the problem is that I see no way of turning a NSMutableArray to NSData, and then going from NSData, back to an NSMutableArray. Does anyone have an idea as to how this issue can be solved?
(I know I can archive the array, but I don't want to do that, I want it to be present in my model).
You could have a binary data attribute in your modeled object, archive the array to data, and hand it off to the object.
But I think the better way would be to have a to-many relationship, instead of using an array directly.
****Edit: Here's how to archive the array into NSData so that it can be used in your managed object***
NSData *arrayData = [NSKeyedArchiver archivedDataWithRootObject:[NSArray arrayWithObjects:#"1",#"2", nil]];
Basically, any class you have which conforms to the NSCoding protocol can be archived in this way. NSArray/NSMutableArray already conform to it. They tell all of their objects to archive themselves, so they must conform too. And all of those objects' members must conform, etc. It's like a tree.
Since your array conforms, and it's an array of NSString (which also conforms), then you're golden.