tags:

views:

204

answers:

1

Hi,

I'm working on an iPhone app that performs some communication with the server to be initialized the first time it's run. I have a class ServerCommunication with methods for each of the basic tasks to be performed (authenticate user, get activation key, download updates, etc.), and a new instance of ServerCommunication is created for each task; I'm not reusing them, although it would be more efficient.

When the user completes the first initialization screen, ServerCommunication gets created four times. I keep track of it with NSLog(@"Initializing ServerCommunication instance %p", self); in its -init method. The second initialization screen also calls ServerCommunication a few times when the user taps the "Next" button, but on its last instantiation, the app hangs with the message -[ServerCommunication insertDataIntoLocalDB:]: message sent to deallocated instance 0xec75b0 in the console. The thing is, 0xec75b0 is the address of the first instance of ServerCommunication I created way back at the first screen.

Why would it be sending messages to that instance? I'm not retaining them anywhere; they're mostly autoreleased. If it helps, all of the methods in that class perform asynchronous downloading of XML data with NSURLConnection and then parse it with NSXMLParser. The parser's delegate method -(void)parserDidEndDocument:(NSXMLParser *)parser then sends off NSNotifications that are received by methods in my view controllers so they know whether to proceed to the next screen or stay there and display an error message.

Help is much appreciated!

A: 

The first thing I would do is turn on NSZombies, which should let you break at the point where your zombie is being messaged.

A common cause of problems like this is when you have objects with weak references to each other that are not allocated and deallocated at the same time. So (hypothetically), some other object stores a pointer to your ServerCommunication object as a delegate or owner. When ServerCommunication is deallocated, it doesn't unregister, and then some time down the road the object holding the weak reference tries to message you.

If I had to completely guess (and I do!) I bet you add your ServerCommunication objects as an NSNotification observer, but never remove them. Try making sure that you do this:

 [[NSNotificationCenter defaultCenter] removeObserver:self];

sometime before deallocation. (It's also possible that there's a more circuitous path involving NSNotification here -- such as a pointer to the ServerCommunication object being passed as data to the view controller, which is then trying to message it.)

peterb
You're right! I needed to `removeObserver` my ServerCommunication instances. Most of my notifications are received elsewhere, but ServerCommunication is registered for one that gets posted when the user taps "next" on the second screen. And since all my previous instances were also registered to receive it (even though they wouldn't have done anything with it), when the notification was finally sent at the end of the second screen, I guess NSNotificationCenter tried to send it to all the previous instances (none of which existed anymore).Thanks a bunch!
Pedro