Erreur "whose view is not in the window hierarchy!"

Bonjour tous le monde,


 


Après avoir terminer mon application, et fait des test a Simulateur Iphone.


Je l'ai installer sur mon mobile, IPhone 5C et d'autres.


 


J'ai une erreur qui arrive quant je passe d'une fenêtre a une autre.


 


je m'explique il vérifie si on est loguer :


 


 1- si on est il continue,


 2- si non il demande de se logue.


 


 Mais dans le terminal j'ai cela :


 


Warning: Attempt to present <test.LoginViewController: 0x10168d4c0> on <test.DetailForSaleTableViewController: 0x10213a200> whose view is not in the window hierarchy!


 


j'ai vue cela :


 


UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: activityController animated: YES completion:nil];


 


[self presentViewController: activityController animated: YES completion:nil];


 


et ne trouve pas comment résoudre cela.


 


Merci de vos aide,


 


Réponses

  • LarmeLarme Membre
    avril 2017 modifié #2

    Tu fais ces 3 lignes à  la suite ?


    C'est un objet de quelle classe le self?


    L'erreur est explicite :


    Tu demandes à  un ViewController (A) de présenter un autre ViewController (B ). Sauf que ce dernier (A) n'est pas présent (visible on va dire), et du coup, il ne peut pas afficher un autre ViewController (B ).


  • CéroceCéroce Membre, Modérateur
    Pour compléter la réponse de Larme: souvent on demande l'affichage dans le block de completion de -[presentViewController:animated:completion:] pour cette raison.
  • Tu fais ces 3 lignes à  la suite ?


    Non c'est un exemple que j'ai pris.


     


    C'est un objet de quelle classe le self?


    ????


     


    L'erreur est explicite :


    Tu demandes à  un ViewController (A) de présenter un autre ViewController (B ). Sauf que ce dernier (A) n'est pas présent (visible on va dire), et du coup, il ne peut pas afficher un autre ViewController (B ).


    Oui c'est ça, mais je ne comprend pas ??


     


    -[presentViewController:animated:completion:]


    OK mais comment je peux faire pour régler cela, le simulateur ne ma jamais donne cette erreur, pourquoi j'ai cela maintenant.


     


     


    voila un bout de mon code :



    let prefs:UserDefaults = UserDefaults.standard
    let isLoggedIn:Int = prefs.integer(forKey: "ISLOGGEDIN") as Int

    if (isLoggedIn != 1) {

    self.performSegue(withIdentifier: "goto_login", sender: self)

    } else {


    }

    Merci a vous,


  • Joanna CarterJoanna Carter Membre, Modérateur

    Tu as mis le code dans quelle méthode de quelle classe ?


  • easydeasyd Membre
    avril 2017 modifié #6

    Bonjour,


     


    Voilà  mon code :



    import UIKit

    class ContainerViewController: UIViewController {


    @IBOutlet weak var containerViewA: UIView!
    @IBOutlet weak var containerViewB: UIView!

    @IBOutlet var menuButton:UIBarButtonItem!
    @IBOutlet var extraButton:UIBarButtonItem!


    override func viewDidLoad() {
    super.viewDidLoad()

    if NetworkViewController.isConnectedToNetwork() == true
    {

    }
    else
    {
    print("Internet connection FAILED")

    let title = NSLocalizedString("No Internet Connection", comment: "TITLE")
    let msg = NSLocalizedString("Make sure your device is connected to the internet.", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)
    }

    if revealViewController() != nil {
    //revealViewController().rearViewRevealWidth = 62
    menuButton.target = revealViewController()
    menuButton.action = #selector(SWRevealViewController.revealToggle(_:))

    revealViewController().rightViewRevealWidth = 230
    extraButton.target = revealViewController()
    extraButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))

    view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    let prefs:UserDefaults = UserDefaults.standard
    let isLoggedIn:Int = prefs.integer(forKey: "ISLOGGEDIN") as Int

    if (isLoggedIn != 1) {

    self.performSegue(withIdentifier: "goto_login", sender: self)

    } else {


    }
    }

    @IBAction func showComponent(sender: UISegmentedControl) {
    if sender.selectedSegmentIndex == 0 {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 1
    self.containerViewB.alpha = 0
    })
    } else {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 0
    self.containerViewB.alpha = 1
    })
    }
    }



    }

    Cela me permet si pas loguer redirection vers le storyboard de connexion.


     


    Voilà ,


     


    P.S : merci encore.

  • Joanna CarterJoanna Carter Membre, Modérateur

    ça y est !


     


    Tu écris le code avant que la vue est visible. Tu devrais le mettre dans viewDidAppear.


  • Trop génial merci a toi j'ai fait les modif est ça fonctionne très bien plus d'erreur.


     


    Code modifier :



    import UIKit

    class ContainerViewController: UIViewController {


    @IBOutlet weak var containerViewA: UIView!
    @IBOutlet weak var containerViewB: UIView!

    @IBOutlet var menuButton:UIBarButtonItem!
    @IBOutlet var extraButton:UIBarButtonItem!


    override func viewDidLoad() {
    super.viewDidLoad()

    if NetworkViewController.isConnectedToNetwork() == true
    {

    }
    else
    {
    print("Internet connection FAILED")

    let title = NSLocalizedString("No Internet Connection", comment: "TITLE")
    let msg = NSLocalizedString("Make sure your device is connected to the internet.", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)
    }

    if revealViewController() != nil {
    //revealViewController().rearViewRevealWidth = 62
    menuButton.target = revealViewController()
    menuButton.action = #selector(SWRevealViewController.revealToggle(_:))

    revealViewController().rightViewRevealWidth = 230
    extraButton.target = revealViewController()
    extraButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))

    view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    }

         func viewWillAppear() {
        
            let prefs:UserDefaults = UserDefaults.standard
            let isLoggedIn:Int = prefs.integer(forKey: "ISLOGGEDIN") as Int
            
            if (isLoggedIn != 1) {
                
                self.performSegue(withIdentifier: "goto_login", sender: self)
                
            } else {
                
                
            }
        }

    @IBAction func showComponent(sender: UISegmentedControl) {
    if sender.selectedSegmentIndex == 0 {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 1
    self.containerViewB.alpha = 0
    })
    } else {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 0
    self.containerViewB.alpha = 1
    })
    }
    }



    }
  • Désolé,


     


    J'ai bien fait des modifications,  après un test en m'authentifient ça fonctionne bien.


     


    Mais quant je suis pas authentification cela dois passer sur le storyboard de demande de connexion et ça ne le fait plus.


     


    Merci a vous,

  • Tu dois pas mettre override func viewWillAppear() plutôt ? Comme t'as fait pour viewDidLoad() ?


    Tu n'appelles pas super.viewWillAppear() dedans ?


     


    Et je pense que pour ton test de connection, dans lequel tu peux faire un self.present(), tu auras le même soucis s'il est dans le viewDidLoad()


  • J'ai corriger cela est j'ai mis :



    import UIKit

    class ContainerViewController: UIViewController {


    @IBOutlet weak var containerViewA: UIView!
    @IBOutlet weak var containerViewB: UIView!

    @IBOutlet var menuButton:UIBarButtonItem!
    @IBOutlet var extraButton:UIBarButtonItem!


    override func viewDidLoad() {
    super.viewDidLoad()

    if NetworkViewController.isConnectedToNetwork() == true
    {

    }
    else
    {
    print("Internet connection FAILED")

    let title = NSLocalizedString("No Internet Connection", comment: "TITLE")
    let msg = NSLocalizedString("Make sure your device is connected to the internet.", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)
    }

    if revealViewController() != nil {
    //revealViewController().rearViewRevealWidth = 62
    menuButton.target = revealViewController()
    menuButton.action = #selector(SWRevealViewController.revealToggle(_:))

    revealViewController().rightViewRevealWidth = 230
    extraButton.target = revealViewController()
    extraButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))

    view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    }

    override func viewDidAppear(_ animated: Bool) {

    let prefs:UserDefaults = UserDefaults.standard
    let isLoggedIn:Int = prefs.integer(forKey: "ISLOGGEDIN") as Int

    if (isLoggedIn != 1) {

    self.performSegue(withIdentifier: "goto_login", sender: self)

    } else {

    }
    }


    @IBAction func showComponent(sender: UISegmentedControl) {
    if sender.selectedSegmentIndex == 0 {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 1
    self.containerViewB.alpha = 0
    })
    } else {
    UIView.animate(withDuration: 0.5, animations: {
    self.containerViewA.alpha = 0
    self.containerViewB.alpha = 1
    })
    }
    }



    }

  • Et ça marche maintenant ? Je suppose vu que tu mets la vraie méthode qui sera appelée (la tienne n'était pas correcte).

     

    Et les deux autres indications de mon précédent commentaire ?

     

    Documentation de viewDidAppear:



    You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.



  • J'utilise cela dans d'autres storyboard :



    @IBAction func favories(_ sender : UIButton) {


    let prefs:UserDefaults = UserDefaults.standard
    let isLoggedIn:Int = prefs.integer(forKey: "ISLOGGEDIN") as Int
    if (isLoggedIn != 1) {
    self.performSegue(withIdentifier: "goto_login", sender: self)

    } else {

    let Ui_nre:NSString = ui_nref.text! as NSString
    let Type_produit:NSString = txtType_produit as NSString
    let emailLabel = (prefs.value(forKey: "EMAIL") as? String)!

    if ( emailLabel.isEqual("") || Type_produit.isEqual(to: "") || Ui_nre.isEqual(to: "")) {

    let alertView:UIAlertController = UIAlertController()
    alertView.title = "Sign in Failed!"
    alertView.message = "Please enter Username and Password"

    do {
    let post:NSString = "user_emails=\(emailLabel)&ref_produit=\(Ui_nre)&type_produit=\(3)" as NSString

    NSLog("PostData: %@",post);

    let url:URL = URL(string:"http://sereveur/myfavorie_user.php")!
    let postData:Data = post.data(using: String.Encoding.ascii.rawValue)!
    let postLength:NSString = String( postData.count ) as NSString
    let request:NSMutableURLRequest = NSMutableURLRequest(url: url)

    request.httpMethod = "POST"
    request.httpBody = postData
    request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.setValue("application/json", forHTTPHeaderField: "Accept")

    var reponseError: NSError?
    var response: URLResponse?
    var urlData: Data?

    do {
    urlData = try NSURLConnection.sendSynchronousRequest(request as URLRequest, returning:&response)
    } catch let error as NSError {
    reponseError = error
    urlData = nil
    }

    if ( urlData != nil ) {
    let res = response as! HTTPURLResponse!;

    if ((res?.statusCode)! >= 200 && (res?.statusCode)! < 300)
    {
    let responseData:NSString = NSString(data:urlData!, encoding:String.Encoding.utf8.rawValue)!

    NSLog("Response ==> %@", responseData);

    let jsonData:NSDictionary = try JSONSerialization.jsonObject(with: urlData!, options:JSONSerialization.ReadingOptions.mutableContainers ) as! NSDictionary

    let success:NSInteger = jsonData.value(forKey: "success") as! NSInteger

    NSLog("Success: %ld", success);

    if(success == 1)
    {

    let title = NSLocalizedString("FAVORITE", comment: "TITLE")
    let msg = NSLocalizedString("Your ad is already registered in your favorite", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)

    //self.dismiss(animated: true, completion: nil)
    } else {
    var error_msg:NSString

    if jsonData["error_message"] as? NSString != nil {
    error_msg = jsonData["error_message"] as! NSString
    } else {
    error_msg = "Unknown Error"
    }

    let title = NSLocalizedString("FAVORITE", comment: "TITLE")
    let msg = NSLocalizedString("Your ad is already registered in your favorite", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)

    }

    } else {

    let title = NSLocalizedString("Error", comment: "TITLE")
    let msg = NSLocalizedString("Account already exists", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)

    }
    } else {
    let alertView:UIAlertController = UIAlertController()
    alertView.title = "Sign in Failed!"
    alertView.message = "Connection Failure"
    if let error = reponseError {
    alertView.message = (error.localizedDescription)
    }

    }
    } catch {
    let title = NSLocalizedString("Error", comment: "TITLE")
    let msg = NSLocalizedString("Account already exists", comment: "Please_enter_all_fields")

    let alert = UIAlertController.init(title: title, message: msg, preferredStyle: .alert)
    self.present(alert, animated: true, completion: nil)


    }
    }

    }
    }

  • Joanna CarterJoanna Carter Membre, Modérateur

    Wouaaaah ! Quelle indentation. tu devrais utiliser plutôt "guard let ... else"


  • Tu sembles utiliser Swift 3, alors favorises URL plutôt que NSURL, URLRequest plutôt que NSURLRequest, Swift Dictionaries plutôt que NSDictionary, etc.


Connectez-vous ou Inscrivez-vous pour répondre.