开发者

[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 {
开发者_JAVA百科    [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.


Can't you make your alertView an @property or instance variable and just set alertView.delegste = nil in MyObject's dealloc?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜