简体   繁体   中英

[self retain], [self autorelease], is this correct when I'm assigned as a delegate?

I solved a crash with something that sounds weird do me : calling [self retain] and [self autorelease].

Here's the case :

MyObject is a subclass of a UIView, so usually it's allocated, put on the view stack, and released. MyObject also has a timer, which will remove itself from the superview. So basically MyObject can be deallocated at anytime. Apart from displaying cool stuf, MyObject is also able to displays a UIAlertView, and waits for the user's choice, so it's the alertView's delegate. The problem is that if the user makes a choice after MyObject is deallocated... well you know EXC_BAD_ACCESS I guess...

So I could have kept a reference to the AlertViews (yes, there are severals), and set the delegate to nil in the MyObject dealloc method. But I couldn't process the choice then (and as there are several, it would make more variable instances, which I don't like.

So what I did is :

//alertView creation
-(void)showAlert{
    [self retain];

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title"
    message:@"message" 
    delegate:self 
    cancelButtonTitle:@"No"
    otherButtonTitles:@"Yes",nil];

    [alertView show];
    [alertView release];
}

//Delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [self autorelease];
    // Do the job
}

I know it's not nice, I've put many comments around this to make other developers that will reuse the code be careful, but I can't see another option. Is it correct ? Is there a better way todo it ?

Keep in mind that the delegate pattern, in order to avoid having a cyclic dependency which prevents the main object as well as the delegate from being released since they both have a reference to each other, requires that the main object does not retain the delegate. So if you create a delegate on the fly and assign it to an object, you have to retain and autorelease it yourself!

Frankly, your program structure is all gnarly, and that's what is causing your trouble. You should move all of the delegate functionality and the responsibility for managing the views into a separate controller object.

First of all, I don't see a problem with retaining self. I also did it in some multi-threaded code. Maybe not the best solution but it worked.

Now, if you want to avoid [self retain], consider the following: Maybe instead of straight deallocating when the timer fires, you instead check if there's an Alert presented. If not, release. If yes, hide the view (but don't remove from superview) and set a flag in a new ivar that the object should be removed from superview. In the sheet's callback, check the flag and if set, remove the view from the superview, releasing it.

你不能让你的alertView成为alertView或实例变量,只需在MyObject的dealloc设置alertView.delegste = nil吗?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM