In my app, I have a NSDictionary
whose keys should be instances of a subclass of NSManagedObject
.
The problem, however, is that NSManagedObject
does not implement the NSCopying
protocol which means that no Core Data objects / instances of NSManagedObject
can be used as dictionary keys even though the -[hash]
method works fine for them.
Was should I do?
NSDictionary / NSMutableDictionary copies keys, and holds strong references to values. NSMapTable is mutable, without an immutable counterpart. NSMapTable can hold keys and values with weak references, in such a way that entries are removed when either the key or value is deallocated.
Main Difference is:NSMutableDictionary is derived from NSDictionary, it has all the methods of NSDictionary. NSMutableDictionary is mutable( can be modified) but NSDictionary is immutable (can not be modified).
An object representing a static collection of key-value pairs, for use instead of a Dictionary constant in cases that require reference semantics.
An NSDictionary will retain it's objects, and copy it's keys. Here are some effects this has had on code I've worked on. Sometimes you get the same object you put in, sometimes not. Immutable objects are optimized to return themselves as a copy .
There are four options:
[object objectID]
or +[NSValue valueWithNonretainedObject:]
seem the most obviousCFDictionaryCreateMutable()
to create a dictionary with retained keys, rather than copied, instead, and then call CFDictionarySetValue()
to store the objects[NSMapTable mapTableWithStrongToStrongObjects]
gives you a purely Objective-C equivalent to CFMutableDictionary
NSCopying
for your managed object subclass, such that it returns self (with a bumped reference count if you're not using ARC)+valueWithNonretainedObject:
is pretty dangerous, since it's possible to be left with a dangling pointer; likely best to avoid.
Storing object IDs is fine, apart from the fact that new objects start out life with a temporary ID. That ID then changes to a permanent one when the context is saved to disk (or -obtainPermanentIDsForObjects:…
is called). Your mapping code needs to be smart enough to handle this unless it can guarantee that all incoming objects already have a permanent ID.
Implementing NSCopying
like this feels a bit icky, but should work just fine. As it happens, this is exactly the approach NSURLSessionTask
takes, I presume for dictionary friendliness.
Prior to OS X 10.8 Mountain Lion, it used to be possible to create a regular NSMutableDictionary
and then call CFDictionarySetValue()
for it. That's no longer the case though; new dictionaries now have proper copy callbacks specified down at the CF level, rather than purely being a feature of NSMutableDictionary
.
I suggest to use [[[myManagedObject objectID] URIRepresentation] absoluteString] as your key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With