2015-05-05 2 views
10

У меня возникли проблемы с отображением моего UIAlertController, потому что я пытаюсь показать его в классе, который не является ViewController.показать UIAlertController вне ViewController

я уже пытался добавить его:

var alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert) 

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil) 

Что не работает ... я не нашел решение, которое работало для меня до сих пор.

+0

Вы являетесь классом, который не является UIViewController, в настоящее время является частично неопровержимым. Подумайте о добавлении делегата или обратного вызова на основе блока, чтобы отобразить предупреждение на контроллере представления, который использует этот класс. – 3lvis

ответ

27

Я написал эту extension над UIAlertController, чтобы вернуть show().
Он использует рекурсию, чтобы найти текущий верхний контроллер представления:

extension UIAlertController { 

    func show() { 
     present(animated: true, completion: nil) 
    } 

    func present(#animated: Bool, completion: (() -> Void)?) { 
     if let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController { 
      presentFromController(rootVC, animated: animated, completion: completion) 
     } 
    } 

    private func presentFromController(controller: UIViewController, animated: Bool, completion: (() -> Void)?) { 
     if let navVC = controller as? UINavigationController, 
      let visibleVC = navVC.visibleViewController { 
       presentFromController(visibleVC, animated: animated, completion: completion) 
     } else 
     if let tabVC = controller as? UITabBarController, 
      let selectedVC = tabVC.selectedViewController { 
       presentFromController(selectedVC, animated: animated, completion: completion) 
     } else { 
      controller.presentViewController(self, animated: animated, completion: completion); 
     } 
    } 
} 

Теперь это так просто, как:

var alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert) 
alertController.show() 

EDIT:

Для Xcode 8.0 & Swift 3:

extension UIAlertController { 

    func show() { 
     present(animated: true, completion: nil) 
    } 

    func present(animated: Bool, completion: (() -> Void)?) { 
     if let rootVC = UIApplication.shared.keyWindow?.rootViewController { 
      presentFromController(controller: rootVC, animated: animated, completion: completion) 
     } 
    } 

    private func presentFromController(controller: UIViewController, animated: Bool, completion: (() -> Void)?) { 
     if let navVC = controller as? UINavigationController, 
      let visibleVC = navVC.visibleViewController { 
      presentFromController(controller: visibleVC, animated: animated, completion: completion) 
     } else 
      if let tabVC = controller as? UITabBarController, 
       let selectedVC = tabVC.selectedViewController { 
       presentFromController(controller: selectedVC, animated: animated, completion: completion) 
      } else { 
       controller.present(self, animated: animated, completion: completion); 
     } 
    } 
} 
+0

Это здорово! Большое спасибо – Michael

+0

Рад, что это работает для вас, я использовал его со многими сценариями VC (modal vc на стеке nav внутри контроллера панели таблеток и т. Д.), Пожалуйста, дайте мне знать, если ситуация, когда это не работает. .. –

+0

SharedApplication не может использоваться в расширении приложения. – SAHM

0

Создайте вспомогательную функцию, которую вы называете из текущего контроллера представления и передать текущий контроллер представления в качестве параметра:

func showAlertInVC(
    viewController: UIViewController, 
    title: String, 
message: String) 
{ 
    //Code to create an alert controller and display it in viewController 
} 
0

Если решение не работает это, вероятно, потому, что там нет окна в тот момент, , У меня была такая же проблема, когда я пытался показать предупреждение в методе application:DidFinishLoadingWithOptions. В этом случае мое решение было проверить, если вид корневой контроллер доступен, а если нет, то добавить уведомление для UIApplicationDidBecomeActiveNotification

NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidBecomeActiveNotification, 
       object: nil, 
       queue: NSOperationQueue.mainQueue()) { 
        (_) in 
         //show your alert by using root view controller 
         //remove self from observing 
        } 
     } 
0

Это должно сработать.

UIApplication.sharedApplication().windows[0].rootViewController?.presentViewController(...) 
Смежные вопросы