Core Data: How do I maintain without retain?
I am trying to debug a very nefarious problem with some iPhone Core Data code.
The setup is this: I have a thread which exists to poll a web service and send its results via NSNotification
to the main thread (passed in the userDict
, a bunch of strings and NSNumber
s). I'm using Tim Hatcher's notification library to pass to the main thread.
NSDictionary* userDict = [Message userDictFromXML:el];
if (userDict != nil)
{
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"InsertMessage" object:nil userInfo:userDict];
}
The main thread receives the userDict, then proceeds to extract its values and insert them into a new managed object. So far so good.
I run into problems with this however, but not immediately. After the thread has posted its results to the main thread, and it save a new object into the context, I can perform a certain series of operations (including a NSFetchRequest
and a couple of relationship assignments) which results in a EXC_BAD_ACCESS
when trying to access one of the properties of the fetched managed object.
The other funny thing is that I can make the problem go away. I can do this by putting a single [userDict retain]
in the thread before I put it inside a NSNotification
to be posted into the main thread to be saved into the managed object. It doesn't matter if I firewall the objects from each other by creating a new NSString
as soon as I receive the values in the receiving thread, it will still crash wi开发者_开发问答thout that retain
.
NSDictionary* userDict = [Message userDictFromXML:el];
if (userDict != nil)
{
[userDict retain]; // NOW THIS WORKS (???)
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"InsertMessage" object:nil userInfo:userDict];
}
What gives ???
So the problem is really with properties going into the managed object, right? The reason the retain fixes things is because that dictionary never gets released, that means whatever else is over-releasing your object is able to do so without crash, and in the end you have a dictionary with a bad pointer in it (since your object has been released).
If you have Snow Leopard, try running with NSZombieEnabled turned on, and use the ObjectAlloc instruments tool. When the zombie gets freed, you can click and find a list of all the places the object was retained and released.
It sounds to me that you need to retain the objects while adding them to the ManagedObject from the Dict. I suspect that adding the retain before you send it through the notification is over retaining, but you are missing a retain on the other side so it is balancing out.
精彩评论