2015-05-05 18 views
10

Mam problem z wyświetleniem mojego kontrolera UIAlert, ponieważ próbuję pokazać go w klasie, która nie jest ViewController.pokaż UIAlertController poza ViewController

Już próbowałem dodanie go:

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

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

Które nie działa ... Nie mogę znaleźć żadnego rozwiązania, które pracowały dla mnie jeszcze.

+0

Jesteś klasy, która nie jest UIViewController teraz jest częściowo untestable. Rozważ dodanie delegata lub bloku oddzwaniania opartego na bloku, aby wyświetlić alert na kontrolerze widoku, który używa tej klasy. – 3lvis

Odpowiedz

27

Napisałem ten extension nad UIAlertController przywrócić show().
Wykorzystuje rekursji, aby znaleźć aktualny górną kontrolera wyświetlania:

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); 
     } 
    } 
} 

Teraz jest tak proste, jak:

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

EDIT:

Dla 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

To świetnie! Wielkie dzięki – Michael

+0

Cieszę się, że to działa dla ciebie, używałem go z wieloma scenariuszami VC (modal vc na stosie nav wewnątrz kontrolera paska kart itp.), Proszę dać mi znać, jeśli jest sytuacja, w której to nie działa. .. –

+0

Aplikacja SharedApplication nie może być używana w rozszerzeniu aplikacji. – SAHM

0

Tworzenie funkcji pomocnika, który nazywamy z bieżącego widoku kontrolera i przekazać bieżący kontroler widoku jako parametr:

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

Jeżeli rozwiązanie nie jest to praca prawdopodobnie dlatego nie ma okna w tym momencie . Miałem ten sam problem, gdy próbowałem wyświetlić widok alertu w metodzie application:DidFinishLoadingWithOptions. W tym przypadku moje rozwiązanie było sprawdzenie, czy widok główny kontroler jest dostępna, a jeśli tak nie jest, a następnie dodać powiadomienie o UIApplicationDidBecomeActiveNotification

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

To powinno działać.

UIApplication.sharedApplication().windows[0].rootViewController?.presentViewController(...) 
Powiązane problemy