1

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

Gabriel.Massana
  • 8,165
  • 6
  • 62
  • 81
AppsDev
  • 12,319
  • 23
  • 93
  • 186
  • Please check if you are calling the alertview in the main thread? – Rose Apr 02 '14 at 11:45
  • You can check it with `[NSThread isMainThread]` – Gabriel.Massana Apr 02 '14 at 11:47
  • I always create the object that shows the alert view within a view controller. It is a strong property. Can I assume it is always called in the main thread, then? Unfortunately I don't know how to cause this crash intentionally – AppsDev Apr 02 '14 at 11:53
  • @Gabriel.Massana if I check `[NSThread isMainThread]` before showing the alert view, will I prevent the app from reaching this crash? – AppsDev Apr 02 '14 at 11:55
  • @AppsDev `[NSThread isMainThread]` is only to check if you are in the main thread. IS to check @Rose comment. – Gabriel.Massana Apr 02 '14 at 11:57
  • please check dispatch_sync(dispatch_get_main_queue(), ^{ alertView show] }); – Rose Apr 02 '14 at 12:15
  • @Rose I'm using TestFlight and the crash report says it is the `Primary Thread Thread 0` – AppsDev Apr 02 '14 at 12:40

3 Answers3

3

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];
}
malex
  • 9,874
  • 3
  • 56
  • 77
0

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.

Sujith Thankachan
  • 3,508
  • 2
  • 20
  • 25
0

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.
simalone
  • 2,768
  • 1
  • 15
  • 20