简体   繁体   English

[自我保留],[自我自动释放],当我被指派为代表时,这是正确的吗?

[英][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]. 我用一些听起来很奇怪的东西解决了崩溃:调用[self retain]和[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是UIView的子类,因此通常将其分配,放在视图堆栈上并释放。 MyObject also has a timer, which will remove itself from the superview. MyObject还有一个计时器,它将自己从superview中删除。 So basically MyObject can be deallocated at anytime. 所以基本上MyObject可以随时解除分配。 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. 除了显示酷的stuf之外,MyObject还能够显示UIAlertView,并等待用户的选择,因此它是alertView的委托。 The problem is that if the user makes a choice after MyObject is deallocated... well you know EXC_BAD_ACCESS I guess... 问题是,如果用户在MyObject被释放后做出选择......那么你知道EXC_BAD_ACCESS我猜...

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. 所以我可以保留对AlertViews的引用(是的,有几个),并在MyObject dealloc方法中将委托设置为nil。 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. 如果是,则隐藏视图(但不要从superview中删除)并在新的ivar中设置一个标志,该对象应从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吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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