Проверьте, показывает ли UIAlertView - PullRequest
40 голосов
/ 27 марта 2010

У меня есть метод, который отправляет данные HTTP и отображает UIAlertView, если есть ошибка. Если у меня есть несколько сообщений HTTP, я буду показывать несколько UIAlertView для каждой ошибки.

Я хочу показать UIAlertView, только если не отображается другой UIAlertView. Как я могу это определить?

Ответы [ 10 ]

59 голосов
/ 19 апреля 2012

Почему бы просто не проверить свойство visible, поддерживаемое классом UIAlertView?

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];
}
52 голосов
/ 27 марта 2010

Для объекта, который вызывает, установите ivar перед вызовом метода show в вашем UIAlertView.

...

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

...

Затем в вашем методе делегата для управления оповещениями установите для флага ivar значение no:

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

Если вы хотите, чтобы оповещения отображались последовательно, я бы отправлял уведомления, чтобы добавить каждое сообщение в очередь, а затем выводить сообщение из очереди только после прекращения оповещения.

25 голосов
/ 27 марта 2010

Если вы можете контролировать другие виды предупреждений, проверьте свойство visible для каждого из них.


В iOS 6 или ранее, когда появляется предупреждение, оно будет перемещено в окно _UIAlertOverlayWindow. Поэтому довольно хрупкий метод состоит в том, чтобы перебрать все окна и проверить, есть ли какие-либо подпредставления UIAlertView.

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;

Это недокументировано, поскольку зависит от внутренней иерархии представлений, хотя Apple не может пожаловаться на это. Более надежным, но еще более недокументированным методом является проверка , если [_UIAlertManager visibleAlert] равно нулю .

Эти методы не могут проверить, отображается ли UIAlertView из SpringBoard.

9 голосов
/ 01 марта 2013
- (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;
}
4 голосов
/ 25 августа 2016

Я думаю, что это будет работать:

-(BOOL) doesAlertViewExist {
    if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
    {
        return NO;//AlertView does not exist on current window
    }
    return YES;//AlertView exist on current window
}
4 голосов
/ 03 октября 2013

Другой вариант, который работает во всем приложении и не требует обхода стека представлений, - это создать подкласс UIAlertView к MyUIAlertView, добавить статическую (классовую) переменную BOOL alertIsShowing и переопределить селектор -(void)show.

В переопределенном селекторе show проверьте переменную alertIsShowing. Если это YES, попробуйте еще раз после задержки (используйте dispatch_after или установите NSTimer). Если это NO, наберите [super show] и назначьте YES на alertIsShowing; когда представление предупреждений скрыто, установите alertIsShowing обратно на NO (вам нужно быть умным в отношении обработки делегата).

Наконец, пройдите и замените все UIAlertView экземпляры на MyUIAlertView.

3 голосов
/ 12 июля 2016

Swift:

func showAlert(withTitle title: String, message: String, viewController: UIViewController) {
    if viewController.presentedViewController == nil { // Prevent multiple alerts at the same time
        let localizedTitle = NSLocalizedString(title, comment: "")
        let localizedMessage = NSLocalizedString(message, comment: "")
        let alert = UIAlertController(title: localizedTitle, message: localizedMessage, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
        alert.addAction(action)

        viewController.presentViewController(alert, animated: true, completion: nil)
    }
}
2 голосов
/ 23 марта 2016
+ (BOOL)checkAlertExist {

    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            return YES;
        }
    }
    return NO;
}
2 голосов
/ 01 июля 2014
// initialize default flag for alert... If alert is not open set isOpenAlert as NO
BOOL isAlertOpen;
isAlertOpen = NO;
if (isAlertOpen == NO) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert is Open" delegate:self cancelButtonTitle:@"Okay!!" otherButtonTitles: nil];
    [alert show];
    // Now set isAlertOpen to YES
    isAlertOpen = YES;
}
else
{
    //Do something
}
1 голос
/ 22 сентября 2015

Некоторые примечания к моему поиску UIAlertView в иерархии представлений:

Я пытался рекурсивно просмотреть все [UIApplication sharedApplication].windows представления, но ничего не смог найти.

Свойство windows документа UIApplication гласит следующее:

Это свойство содержит объекты UIWindow, в настоящее время связанные с приложение. Этот список не включает окна, созданные и управляемые system , например, окно для отображения строки состояния.

Так что это заставило меня осознать, что UIWindow, где может находиться UIAlertView, даже не представлен нам.

ОДНАКО, есть также свойство на UIApplication, которое называется keyWindow. Пройдя через это, я нашел частные классы, которые составляли бы представление с предупреждением:

В iOS 7: _UIModalItemHostingWindow, _UIModalItemAlertContentView, _UIBackdropEffectView и т. Д.

В iOS 8: _UIAlertControllerActionView, _UIAlertControllerShadowedScrollView, _UIBackdropView и т. Д.

Я не смог найти UIAlertView, который я представил, а скорее набор классов, которые составляют его внутренне. Таким образом, чтобы ответить на первоначальный вопрос , вы, вероятно, можете использовать свойство keyWindow и посмотреть, заметили ли вы эти классы, но ваше приложение может быть отклонено за попытку проверки на наличие закрытых классов.

Для людей, использующих более новую версию, UIAlertController, доступную для iOS 8, может получить ссылку на нее, используя: [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.

...