Check if a UIAlertView is showing

50,260

Solution 1

On the object that calls set an ivar before invoking the show method on your UIAlertView.

...

if (!self.alertShowing) {
    theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
    self.alertShowing = YES;
    [theAlert show];
}

...

Then in your delegate method for the alert manage setting your flag ivar to no:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
  ...
      self.alertShowing = NO;
}

If you want the alerts to show sequentially, I would post notifications to add each message to a queue and then only take a message off the queue after an alert is dismissed.

Solution 2

Why not just check the visible property, maintained by the UIAlertView class?

if (_alert) //alert is a retained property
{
    self.alert = [[[UIAlertView alloc] initWithTitle:@"Your Title"
                                             message:@"Your message" 
                                            delegate:self
                                   cancelButtonTitle:@"Cancel"
                                   otherButtonTitles:@"OK"] autorelease];
}
if (!_alert.visible)
{
    [_alert show];
}

Solution 3

If you can control the other alert views, check the visible property for each of them.


In iOS 6 or before, when an alert appears, it will be moved to a _UIAlertOverlayWindow. Therefore, a pretty fragile method is to iterate through all windows and check if there's any UIAlertView subviews.

for (UIWindow* window in [UIApplication sharedApplication].windows) {
  NSArray* subviews = window.subviews;
  if ([subviews count] > 0)
    if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
      return YES;
}
return NO;

This is undocumented as it depends on internal view hierarchy, although Apple cannot complain about this. A more reliable but even more undocumented method is to check if [_UIAlertManager visibleAlert] is nil.

These methods can't check if a UIAlertView from SpringBoard is shown.

Solution 4

- (BOOL)checkAlertExist {
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        if ([subviews count] > 0) {
            for (id cc in subviews) {
                if ([cc isKindOfClass:[UIAlertView class]]) {
                    return YES;
                }
            }
        }
    }
    return NO;
}

Solution 5

Another option that works across the entire app and doesn't involve walking the view stack is to subclass UIAlertView to MyUIAlertView, add a static (class) variable BOOL alertIsShowing, and override the -(void)show selector.

In your overridden show selector, check the alertIsShowing variable. If it's YES then try again after a delay (use dispatch_after or set an NSTimer). If it's NO, go ahead and call [super show] and assign YES to alertIsShowing; when the alert view is hidden, set alertIsShowing back to NO (you'll need to be clever about handling the delegate).

Finally, go through and replace all UIAlertView instances with MyUIAlertView.

Share:
50,260
Ricibald
Author by

Ricibald

Generic enthusiast

Updated on July 09, 2022

Comments

  • Ricibald
    Ricibald almost 2 years

    I have a method that posts HTTP data and displays a UIAlertView if there is an error. If I have multiple HTTP post I will show multiple UIAlertView for every error.

    I want to show a UIAlertView only if is not showing other UIAlertView. How can I determine this?

  • Rahul Vyas
    Rahul Vyas over 12 years
    one typo in your code "UIView* subviews = window.subviews; " it should be NSArray* subviews = window.subviews; by the way it helped me a lot thanks.
  • Gargo
    Gargo over 11 years
    what if alert is showing but it can belong to other viewcontrollers and you don't know to each one?
  • Chip Coons
    Chip Coons over 11 years
    That sounds like a different question than the original poster asked. With the first part of the answer provide, it is implied that the owning viewcontroller is known, so your follow-up does not make sense.
  • sam-w
    sam-w over 11 years
    No need to have an ivar, just check visible property, as in the answer below.
  • Saran
    Saran over 10 years
    I checked isFirstResponder of the alert view for true, that also worked.
  • Chip Coons
    Chip Coons over 10 years
    The visible property was not exposed at the time the original question was asked. Feel free to vote up the later answer if it is more correct now, but two years passed between the original question and the shift to properties (including visible).
  • Womble
    Womble about 10 years
    This will not work in iOS 7. The first subview could be a container. So you'd have to walk the entire possible tree.
  • LiangWang
    LiangWang almost 10 years
    @Deepesh, have you found solution ?
  • LiangWang
    LiangWang almost 10 years
    @Womble, so have you found solution?
  • Deepesh
    Deepesh almost 10 years
    @Jacky, I am not found any right solution ... if you found any solution ... please paste your valuable answer ....Thanks
  • andreacipriani
    andreacipriani almost 10 years
    This code is not thread-safe. If multiple threads can show the alert, you should put this code in a @synchronized block, or you can have more than one alert.
  • Alex Zavatone
    Alex Zavatone almost 9 years
    Make a category on UIAlertView (now UIAlertController) that returns ![self.view isHidden] as the value of alertShowing. If you give the alert's view a tag, that you have defined as an enum you can check that view by the tag's enum name.
  • KoreanXcodeWorker
    KoreanXcodeWorker almost 8 years
    From iOS9, the replaced 'UIAlertController' doesn't have the property 'visible'.
  • Kingalione
    Kingalione almost 8 years
    viewntroller.presentedViewController == nil did the trick. thanks
  • garie
    garie about 7 years
    I like this answer (although I subclassed UIAlertController - if you're using both I would think you'd need to keep track of both). I did end up using a counter rather than a boolean. This way, if you attempt to show two alerts at the same time, you won't accidentally set the boolean to false if the appear/disappear methods get called out of sync from what you expect.
  • Popmedic
    Popmedic over 5 years
    less code -(BOOL) doesAlertViewExist { return ![[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]]; }