AppsDev
AppsDev

Reputation: 12499

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

Upvotes: 1

Views: 1765

Answers (3)

simalone
simalone

Reputation: 2768

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.

Upvotes: 0

Sujith Thankachan
Sujith Thankachan

Reputation: 3506

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.

Upvotes: 0

malex
malex

Reputation: 10096

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];
}

Upvotes: 3

Related Questions