web-dev-qa-db-fra.com

Afficher l'alerte dans AppDelegate in Swift

J'essaie le prochain extrait de code:

var alert = UIAlertController(title: "Alert", message: "Cannot connect to : \(error!.localizedDescription)", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)

dans mon AppDelegate, mais cela m'imprime la prochaine erreur dans la console:

Warning: Attempt to present <UIAlertController: 0x7ff6cd827a30> on <Messenger.WelcomeController: 0x7ff6cb51c940> whose view is not in the window hierarchy!

Comment puis-je réparer cette erreur?

22
Orkhan Alizade

C'est ce que j'utilise maintenant pour le faire.

var alertController = UIAlertController(title: "Title", message: "Any message", preferredStyle: .ActionSheet)
var okAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) {
                    UIAlertAction in
                    NSLog("OK Pressed")
                }
var cancelAction = UIAlertAction(title: "No", style: UIAlertActionStyle.Cancel) {
                    UIAlertAction in
                    NSLog("Cancel Pressed")
                }
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
27
Jorge L Hernandez

Swift 3

let alert = UIAlertController(title: "Test", message:"Message", preferredStyle: UIAlertControllerStyle.alert)

// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))

// show the alert
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
15
Safad Funy

Swift 3.0 ou supérieur, fonctionne dans toutes les conditions, comme dans le cas d'une barre d'onglets, d'une vue présentée, etc.

let alert = UIAlertController(title: "Test", message:"Message", preferredStyle: UIAlertControllerStyle.alert)

// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))

// show alert
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert + 1;
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alertController, animated: true, completion: nil)
12
emraz

Selon la réponse de Jorge, mis à jour pour Swift 4

let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
        UIAlertAction in
        NSLog("OK Pressed")
    }
let cancelAction = UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.cancel) {
        UIAlertAction in
        NSLog("Cancel Pressed")
    }
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
8
Chris Herbst

J'ai eu le même problème.

Je l'ai corrigé en présentant UIAlertController dans Main Queue.

Le code ressemble à suivre.

let alert = UIAlertController(title: "My Title", message: "My Message", preferredStyle: .alert)

let actionYes = UIAlertAction(title: "Yes", style: .default, handler: { action in
print("action yes handler")
})

let actionCancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { action in
print("action cancel handler")
})

alert.addAction(actionYes)
alert.addAction(actionCancel)

DispatchQueue.main.async {
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}
7
Rashesh Bosamiya

Je suppose que vous appelez cet extrait de code à partir de applicationDidFinishLunchingWithOptions:. Je l'ai essayé en fait parce que je devais le faire. Le problème est le suivant: vous essayez de corriger mais le ViewController créé et présenté par AppDelegate est sur le point d’être affiché à l’écran. Avant cela, le fragment de code tente de créer un alertView et de le placer au-dessus de View inexistant le RootViewController. 

Ce que je voudrais faire est de le déplacer vers un autre appel de délégué qui est garanti d'être appelé après la présentation de RootViewController.

    func applicationDidBecomeActive(application: UIApplication) {
     //This method is called when the rootViewController is set and the view.
     // And the View controller is ready to get touches or events.
    var alert = UIAlertController(title: "Alert", message: "Cannot connect to :", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
    self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)

    }

Mais comme toujours, connaissez la responsabilité de l'AppDelegate. Il consiste à gérer le cycle de vie de l'application et les appels et événements délégués à l'échelle de l'application. Si mettre du code ici a du sens, alors faites-le. Mais si vous préférez mettre le code sur le rootViewController ou d’autres composants, réfléchissez-y aussi.

Quoi qu'il en soit, espérons que cela aide. À votre santé!

3
kandelvijaya

Avez-vous essayé d'utiliser UIApplication.shared.keyWindow?.rootViewController?.present(...)?

3
Muli

Je suggère de ne pas faire cela dans le AppDelegate. Le délégué de l'application avait l'intention de gérer les fonctions de délégation depuis le système d'exploitation plutôt que de mettre en œuvre des éléments tels que des vues d'alerte.

Si vous souhaitez présenter une vue d'alerte ici au début de l'application, je le ferais en l'implémentant dans votre premier contrôleur de vue. 

0
Swinny89