Ich habe gerade ein Single View Application-Projekt mit der ViewController-Klasse erstellt. Ich möchte einen UIAlertController von einer Funktion anzeigen, die sich in meiner eigenen Klasse befindet.
Hier ist meine Klasse mit einer Warnung.
class AlertController: UIViewController {
func showAlert() {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil)
}
}
Hier ist ViewController, der die Warnung ausführt.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showAlertButton(sender: AnyObject) {
var alert = AlertController()
alert.showAlert()
}
}
Das ist was ich bekomme, statt schöne Alarmbereitschaft.
Warnung: Versuch, UIAlertController: 0x797d2d20 auf Sprint1.AlertController: 0x797cc500 zu präsentieren, dessen Ansicht nicht in der Fensterhierarchie ist!
Was soll ich machen?
Wenn Sie Ihre UIAlertController
von einem modalen Controller aus instanziieren, müssen Sie dies in viewDidAppear
tun, nicht in viewDidLoad
. Andernfalls erhalten Sie eine Fehlermeldung.
Hier ist mein Code (Swift 4):
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alertController = UIAlertController(title: "Foo", message: "Bar", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
Sehen wir uns Ihre Ansichtshierarchie an. Sie haben eine ViewController
. Dann erstellen Sie eine AlertController
, fügen diese nicht Ihrer Hierarchie hinzu und rufen eine Instanzmethode auf, die versucht, die AlertController
als präsentierenden Controller zu verwenden, um nur einen anderen Controller anzuzeigen (UIAlertController
) .
+ ViewController
+ AlertController (not in hierarchy)
+ UIAlertController (cannot be presented from AlertController)
Um Ihren Code zu vereinfachen
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showAlertButton(sender: AnyObject) {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil)
}
}
Das wird funktionieren.
Wenn Sie die Variable AlertController
für etwas benötigen, müssen Sie sie zuerst der Hierarchie hinzufügen, z. mit addChildViewController
oder mit einem anderen presentViewController
-Aufruf.
Wenn Sie möchten, dass die Klasse nur ein Helfer für das Erstellen von Alarmen ist, sollte dies folgendermaßen aussehen:
class AlertHelper {
func showAlert(fromController controller: UIViewController) {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
controller.presentViewController(alert, animated: true, completion: nil)
}
}
genannt als
var alert = AlertHelper()
alert.showAlert(fromController: self)
Sie können die unten stehende Funktion verwenden, um Alerts von überall aus aufzurufen, wo diese Methoden in AnyClass enthalten sind
class func topMostController() -> UIViewController {
var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
while ((topController?.presentedViewController) != nil) {
topController = topController?.presentedViewController
}
return topController!
}
class func alert(message:String){
let alert=UIAlertController(title: "AppName", message: message, preferredStyle: .alert);
let cancelAction: UIAlertAction = UIAlertAction(title: "OK", style: .cancel) { action -> Void in
}
alert.addAction(cancelAction)
AnyClass.topMostController().present(alert, animated: true, completion: nil);
}
Dann ruf an
AnyClass.alert(message:"Your Message")
Schreiben Sie die folgenden 3 Zeilen, alles was wir tun müssen, ist dies.
Swift 3.0
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
Swift 2.0
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: flag, completion: completion)
}
Wenn Sie eine separate Klasse für die Anzeige dieser Warnung erstellen möchten, müssen Sie die Unterklasse NSObject und nicht UIViewController verwenden.
Übergeben Sie die ViewControllers-Referenz, von der aus sie initiiert wird, an die Funktion showAlert, damit Sie die Alarmansicht dort präsentieren können.
Hier ist der Code eines UIAlertControllers in einer Utility.Swift-Klasse (kein UIViewController) in Swift3, Danke Mitsuaki!
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
func warningAlert(title: String, message: String ){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (action) -> Void in
}))
// self.present(alert, animated: true, completion: nil)
presentViewController(alert: alert, animated: true, completion: nil)
}
Das hat für mich funktioniert:
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
Implementierung:
UIViewController * topViewController = [self topViewController];
Verwendung mit Alert:
[topViewController presentViewController:yourAlert animated:YES completion:nil];
Sie können eine Benachrichtigung aus einer beliebigen Klasse in Ihrer App senden (die UIKit verwendet: #import <UIKit/UIKit.h>
).
Es half mir, eine kleine Verzögerung zwischen der viewDidLoad-Methode und dem Auslösen der Alert-Methode einzuhalten:
[self performSelector:@selector(checkPhotoPermission) withObject:nil afterDelay:0.1f];