Checking for a valid delegate object before sendin

2019-05-10 03:26发布

问题:

I am trying to implement the delegate Pattern in Objective-C, however I am experiencing a Bad Access exception when invoking the delegate sometimes. It seems this is caused by the delegate being released. Apple does not recommend to retain delegates.

How can I check my delegate if is still valid before trying to send it a message?

回答1:

If there's a chance that the delegate will get released by the setter, then there's something wrong with your design. You should only set delegates on objects that have a shorter lifespan than the delegate itself. For example, setting a delegate on a subview/controller is fine, because the subview/controller has a shorter lifespan than the caller.

AFAIK, there is no reliable way to detect if an object has been released already.



回答2:

What Apple means about not retaining delegates is that objects should not retain their delegates because they don't own them. These are only objects that handle messages.

That doesn't mean that you shouldn't retain delegates at all. The object that creates the delegate needs to own it. In the context of non-GC apps this means it should handle the retain and release cycle, and for GC apps, it means that the controller object keeps hold of a pointer to the delegate in an iVar.

without seeing some code or the error message, it is hard to find the root of this problem.



回答3:

In a photoviewer application I'm using asynchronous http to load images; it happens that the user often dismisses the current view (referenced by my async http object through a delegate) before the http download completed causing a BAD_ACCESS when calling the view controller delegate method. I solved this by setting the .delegate to nil inside the dealloc block of the view controller



回答4:

I'd like to share my experience also, which is very similar to Nico's one.

I've been working with a modified example of LazyTablesCode, wich is an example that comes direcly from Apple and loads images in a UITableView asynchronously. Communication between the downloader and the view it's made via delegates.

In my code, I had the problem that sometimes the load of the image finishes when the form that should be called through the delegate has been released. I've been forced to add this piece of code inside the code of the viewController (dealloc method):

if (self.nsDictionaryWithObjectsDownloading != nil) {
    for (id theKey in self.nsDictionaryWithObjectsDownloading) {
        Myobj *downloader = [self.nsDictionaryWithObjectsDownloading objectForKey:theKey];
        downloader.delegate = nil;
    }
}

It seems that these lines are solving the problem. Anyway It would be very appreciated opinions about if it's a good solution or not or even about memory issues when doing downloader.delegate = nil;

Thanks and greetings,