简体   繁体   中英

UIAlertView crashes when button tapped: how to solve?

I have a class that I instance to show an alert view like this:

- (void)showAlert
{       
  UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Do you want to try again?"
                                                        message:nil
                                                       delegate:self
                                              cancelButtonTitle:@"Yes"
                                              otherButtonTitles:@"No", nil];

  [alertView show];
}

}

I need self to be the delegate because I need alertView:didDismissWithButtonIndex: to be called to perform some actions when the user taps the alert view's button. This usually works well, but from time to time, I get this crash:

SIGSEGV
UIKit-[UIAlertView(Private) modalItem:shouldDismissForButtonAtIndex:]

I guess this is because the delegate, for any reason, was released, right? Or is this because what was released was the alert view? How could I solve this? I need the alert view to have a delegate, and I've reading several related posts and I couldn't find an answer that fits my scenario.

I'm testing in iOS 7.0, I don`t know if that could have to do with the issue.

Thanks in advance

It seems that you tap alert when its delegate is released:

delegate:self

It happens because UIAlertView delegate property is of assign type (not weak!). So your delegate potentially can point to released object.

Solution:

in dealloc method you need to clear delegate for your alertView

- (void)dealloc
{
    _alertView.delegate = nil;
}

But before you need to make iVar _alertView and use it for your alertViews

- (void)showAlert
{       
     _alertView = ...;

     [_alertView show];
}

Update your code as follows:

- (void)showAlert {       
  UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Do you want to try again?"
                                                        message:nil
                                                       delegate:self
                                              cancelButtonTitle:@"Yes"
                                              otherButtonTitles:@"No", nil];

  [alertView show];
}

Its due to you are missing the nil for otherButtonTitles part.

Missing sentinel in method dispatch warning will be shown if you didn't add nil .

That's because the alertView's delegate object released while clicking the button. I think it's a bug of SDK:

@property(nonatomic,assign) id /*<UIAlertViewDelegate>*/ delegate;    // weak reference

should be:

@property(nonatomic, weak) id /*<UIAlertViewDelegate>*/ delegate;    // weak reference

To fix the issue:

  1. add a weak delegate for UIAlertView using association.
  2. swizzle the init, setDelegate: delegate methods, set alertView delegate to self, set step 1 weak delegate with the param delegate.
  3. implement all delegate methods, deliver the methods using the weak delegate.

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