如果视图被取消,请单击UIAlertView崩溃应用程序

tes*_*ing 4 iphone cocoa-touch uiviewcontroller uialertview dismiss

UIAlertView如果发生错误,则显示A. 但与此同时UIAlertView,所谓的观点被驳回(因此被释放).如果用户单击确定,则应用程序崩溃,因为已发送到已发布实例的消息.这会导致您的应用崩溃:

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
alertView = nil;
[self.navigationController popViewControllerAnimated:YES];
Run Code Online (Sandbox Code Playgroud)

我以为这UIAlertView是一个独立的单位.但似乎并非如此.有没有办法可以避免应用程序崩溃(除了不解除视图)?

Soo*_*uNe 10

代表在UIAlertView被解雇时被调用,因此在您的情况下:

delegate:self
Run Code Online (Sandbox Code Playgroud)

代理不会保留,例如添加到数组中的对象,或子视图.所以在你的情况下,当你打电话:

[self.navigationController popViewControllerAnimated:YES];
Run Code Online (Sandbox Code Playgroud)

self最有可能被释放,并且当用户解除警报时,self被调用,但是已经被释放,因此它不再存在.

一个简单的方法来检查,这是把一个记录的语句,像NSLog(@"I'm gone");selfdealloc方法,如果它跑了,那么你知道你self不在身边了,而且发送给它的任何消息都会导致系统崩溃.

  • 我在下面的答案中提出了一个不同的选择:在取消分配视图时,只需取消设置委托. (2认同)

Yet*_*osh 5

使UIAlertView成为视图控制器的保留属性,以便您可以在dealloc中引用它,然后在取消分配视图控制器时将警报视图的委托设置为nil.

确保在解除保留的警报视图并在dealloc上正确释放.

例如:

@interface MyViewController : UIViewController <UIAlertViewDelegate> {
    UIAlertView *alertView;
}

@property (nonatomic, retain) UIAlertView *alertView;



@implementation MyViewController

@synthesize alertView;

- (void)showAlert {
    if (alertView) {
        // if for some reason the code can trigger more alertviews before
        // the user has dismissed prior alerts, make sure we only let one of
        // them actually keep us as a delegate just to keep things simple
        // and manageable. if you really need to be able to issue multiple
        // alert views and be able to handle their delegate callbacks,
        // you'll have to keep them in an array!
        [alertView setDelegate:nil];
        self.alertView = nil;
    }
    self.alertView = [[[UIAlertView alloc]
                       initWithTitle:@"Error"
                       message:@"Something went wrong"
                       delegate:self
                       cancelButtonTitle:@"Cancel"
                       otherButtonTitles:@"Retry",nil] autorelease];
    [alertView show];
}

- (void)alertView:(UIAlertView *)alertViewParam didDismissWithButtonIndex:(NSInteger)buttonIndex {
    self.alertView = nil; // release it
    // do something...
}

- (void)dealloc {
    [alertView setDelegate:nil]; // this prevents the crash in the event that the alertview is still showing.
    self.alertView = nil; // release it
    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

这里的缺点是,当用户解除警报视图时,您将无法处理警报视图的回调.但是,由于你的控制器已经消失/释放,大概你不需要.如果这样做,则必须将警报视图的委托设置为将持续存在的内容.


aeg*_*orz -2

确保您正在实施该UIAlertViewDelegate协议。如果您不关心警报何时被解除,只需使用 delegate as 进行 init 即可nil

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"test" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
Run Code Online (Sandbox Code Playgroud)