2014-10-17 3 views
6

Разница между наследием UIAlertView и новым UIAlertController заключается в том, что последний должен быть представлен на конкретном диспетчере просмотра с presentViewController:animated:completion:. Это создает неудобную проблему для моего случая использования: что, если на экране отображается второй экран управления представлением (например, диалоговое окно с ошибкой из-за отказа сетевого соединения), если есть UIAlertController (например, диалоговое окно оценки). Я испытал, что в этом случае второй UIAlertController просто не отображается.Показать UIAlertController, если уже отображается предупреждение

Редактировать: На данный момент я пытаюсь показать предупреждение, я не знаю, есть ли в данный момент что-либо.

Как вы справляетесь с этой ситуацией?

+0

[Эта нить] [1] объясняют правильно, как решать подобные проблемы [1]: http://stackoverflow.com/questions/21179922/can-i-check-if- any-uialertview-display-right-now –

+0

Решения в другом потоке хрупки и уродливы и, вероятно, будут разбиты на iOS8. – fabb

ответ

4

Я нашел обходной путь, чтобы выяснить, какие ViewController я представляем предупредить. Я также отправил ответ here:

@implementation UIViewController (visibleViewController) 

- (UIViewController *)my_visibleViewController { 

    if ([self isKindOfClass:[UINavigationController class]]) { 
     // do not use method visibleViewController as the presentedViewController could beingDismissed 
     return [[(UINavigationController *)self topViewController] my_visibleViewController]; 
    } 

    if ([self isKindOfClass:[UITabBarController class]]) { 
     return [[(UITabBarController *)self selectedViewController] my_visibleViewController]; 
    } 

    if (self.presentedViewController == nil || self.presentedViewController.isBeingDismissed) { 
     return self; 
    } 

    return [self.presentedViewController my_visibleViewController]; 
} 

@end 

// To show a UIAlertController, present on the following viewcontroller: 
UIViewController *visibleViewController = [[UIApplication sharedApplication].delegate.window.rootViewController my_visibleViewController]; 
3

Поскольку UIAlertControllor само по себе является UIViewController, вы можете представить вторую UIAlertController поверх первой, представляя из существующего:

alertController.PresentViewController(alertController2, animated: true, completionHandler: null); 
+0

Проблема заключается в том, что сначала нужно сначала найти верхний представленный диспетчер представлений. Предположим, я не знаю, есть ли какие-либо предупреждения или другие представленные viewcontrollers. – fabb

+0

Используйте это, чтобы получить верхнюю ViewController: \t частный UIViewController GetTopPresentedViewController() \t { \t \t UIViewController currentVC = это.ViewController; \t \t в то время как (истинно) \t \t { \t \t \t UIViewController nextVC = currentVC.PresentedViewController; \t \t \t если (nextVC == NULL) \t \t \t { \t \t \t \t возвращение currentVC; \t \t \t} \t \t \t \t currentVC = nextVC; \t \t \t} \t \t} – Bbx

+0

увидеть мой ответ - не забудьте 'isBeingDismissed' флаг. – fabb

0

Этот код выполняет требование, когда приложение должно представить некоторое предупреждение в окне и перед присутствовать его проверки, что если есть какие-либо другие AlertController представлены уже, если представлено затем представить уведомление о появился Alertcontroller иначе представить его на окне.

Вот еще одна альтернатива, вы можете оптимизировать ее в соответствии с вашими требованиями.

 func showAlert(message:String) { 

     if let alert = self.checkIfAlertViewHasPresented() { 
      alert.presentViewController(alertController, animated: true, completion: nil) 

     } else { 
      self.window?.rootViewController!.presentViewController(alertController, animated: true, completion: nil) 
     } 
    } 

    func checkIfAlertViewHasPresented() -> UIAlertController? { 

     if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { 
      while let presentedViewController = topController.presentedViewController { 
       topController = presentedViewController 
      } 
      if topController is UIAlertController { 
       return (topController as! UIAlertController) 
      } else { 
       return nil 
      } 
     } 
     return nil 
    } 
+0

Это не распространяется на несколько особых случаев, которые рассматриваются в принятом ответе. – fabb

+0

@fabb Согласен с вами. Я уже говорил об этом, прежде чем писать код о состоянии, выполняемом куском кода. Я рассматриваю свой ответ как дополнительный вариант, если у какого-то разработчика-новичка возникнет проблема с пониманием других сложных условий. – iDevAmit

+0

ИМХО особенно новичкам следует научить делать что-то правильно, без обид – fabb

0

Это то, что я использую. этот способ, если предупреждение уже отображается, Я предпочитаю, чтобы пользователь отклонил его, а не приложение. Итак, если представление уже представляет предупреждение, я просто жду 5 секунд и повторю попытку.

Я просто хочу добавить, я не испытывал этого слишком много, но он работает. (Из 1 теста, который я сделал), поэтому я надеюсь, что у меня что-то не хватает, потому что я долго думал об этой проблеме, и это решение звучит слишком легко :)

-(void) alertUserWithTitle:(NSString*) title Message:(NSString*) message 
{ 
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:title                    message:message 
                      preferredStyle:UIAlertControllerStyleAlert]; 

        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault 
                      handler:^(UIAlertAction * action) {}]; 

        [alert addAction:defaultAction]; 

        if(self.presentedViewController == nil) 
        { 
         [self presentViewController:alert animated:YES completion:nil]; 
        }else 
        { 
         double delayInSeconds = 2.0; 
         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 

         dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 

          [self alertUserWithTitle:title Message:message]; 

         }); 

        } 
} 
+0

Хорошо для некоторых случаев использования. Не так идеально, если предупреждение должно блокировать дальнейшее взаимодействие с пользователем. – fabb

0

Вот решение я использую в Swift 3. это функция, которая показывает предупреждение для пользователя, и если вы называете его несколько раз, прежде чем пользователь отклонил предупреждение , он добавит новый текст предупреждения в предупреждение, которое уже представлено. Если появится какое-то другое представление, предупреждение не появится. Не все согласятся с этим поведением, но оно работает хорошо для простых ситуаций.

extension UIViewController { 
    func showAlert(_ msg: String, title: String = "") { 
     if let currentAlert = self.presentedViewController as? UIAlertController { 
      currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)" 
      return 
     } 

     // create the alert 
     let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert) 
     alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) 

     // show the alert 
     self.present(alert, animated: true, completion: nil) 
    } 
} 
Смежные вопросы