представяне, чийто изглед не е в предупреждението за йерархията на прозореца

Нов съм в програмирането и swift и се опитах да прочета някои решения в препълването на стека, но честно казано не разбирам отговора :(

Имам 2 контролера за изглед. homeVC и LoginVC. homeVC е моят първоначален контролер за изглед. в viewDidLoad имам функция на firebase, която може да провери дали потребителят е влизал преди или не. ако не, тогава потребителят ще бъде изпратен към loginVC. ето моят опростен код в HomeVC

import UIKit
import Firebase


class HomeVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // to check whether the user has already logged in or not
        Auth.auth().addStateDidChangeListener { (auth, user) in
            if user == nil {
                let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
                self.present(login, animated: true, completion: nil)
            }
        }

        print("user enter homeVC")

    }



}

и тук е моят loginVC

import UIKit
import Firebase
import GoogleSignIn

class LoginVC : UIViewController, GIDSignInUIDelegate {

    @IBOutlet weak var googleButton: GIDSignInButton!
    @IBOutlet weak var emailButton: UIButton!



    override func viewDidLoad() {
        super.viewDidLoad()


         // delegate declaration
         GIDSignIn.sharedInstance().uiDelegate = self

    }

    @IBAction func googleButtonDidPressed(_ sender: Any) {
        GIDSignIn.sharedInstance().signIn()
    }




}

приложението може да работи както очаквах. но има предупреждение в моята област за отстраняване на грешки:

Предупреждение: Опит за представяне на LoginVC: 0x7fc315714f40 на HomeVC: 0x7fc3155095c0, чийто изглед не е в йерархията на прозореца!

разбира се проблемът е в тези редове код

let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)

доколкото знам, ако изгледът е подреден в слоя на контролера за навигация, тогава, ако искам да се преместя в друг контролер за изглед, трябва да използвам метода perform segue.

Но в този случай между homeVC и LoginVC не са подредени в един и същ навигационен контролер. така че няма йерархия. ето защо използвам този ред код, за да се преместя към друг контролер за изглед (loginVC). но не разбирам защо се казва "изгледът не е в йерархията на прозореца!"

И така, какво трябва да направя, за да пропусна това предупреждение?


person Alexa289    schedule 18.01.2018    source източник
comment
изгледът все още не е готов във viewDidLoad. Опитайте същия код във viewDidAppear   -  person harsha yarabarla    schedule 18.01.2018


Отговори (6)


Вашият LoginVC е напълно наред.

Трябва обаче да промените своя HomeVC, както предложи @Sh_Khan, и да преместите кода за тестване от viewDidLoad на viewDidAppear:

import UIKit
import Firebase

class HomeVC: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // HomeVC.view was added to a view hierarchy
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // to check whether the user has already logged in or not
        Auth.auth().addStateDidChangeListener { (auth, user) in
            if user == nil {
                let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
                self.present(login, animated: true, completion: nil)
            }
        }
    }
}

Обяснение

Вашият viewDidLoad метод се извиква преди viewController да бъде представен, така че в този момент не може наистина да представи друг изглед контролер (тъй като самият той не е представен), viewDidLoad документация:

Извиква се, след като изгледът на контролера се зареди в паметта.

Този метод се извиква, след като контролерът на изгледа е заредил своята йерархия на изгледа в паметта. Този метод се извиква независимо дали йерархията на изгледа е заредена от nib файл или е създадена програмно в метода loadView(). Обикновено отменяте този метод, за да извършите допълнителна инициализация на изгледи, които са заредени от nib файлове.

В този момент viewController все още не е в йерархията на прозореца.

viewDidAppear обаче се извиква, когато view е представен и става част от йерархията на прозореца, viewDidAppear документация:

Уведомява контролера на изгледа, че неговият изглед е добавен към йерархия на изглед.

Можете да замените този метод, за да изпълнявате допълнителни задачи, свързани с представянето на изгледа. Ако отмените този метод, трябва да извикате super в някакъв момент от вашата реализация.

Не забравяйте да се обадите на super.viewDidAppear по време на отмяната му.

person Milan Nosáľ    schedule 18.01.2018

Javascript е език с една нишка. Трябва да опитате напр.: $loading.show(0, function(){obj.filters[index] = filter; //all rest of filters logic here});
person Sh_Khan    schedule 18.01.2018

TLDR; Трябва да преместите кода си към viewDidAppear

viewDidLoad()

Този метод се извиква, след като контролерът на изгледа е заредил своята йерархия на изгледа в паметта. Този метод се извиква независимо дали йерархията на изгледа е заредена от nib файл или е създадена програмно в метода loadView(). Обикновено отменяте този метод, за да извършите допълнителна инициализация на изгледи, които са заредени от nib файлове. Документи на Apple

Така че изгледът все още е само в паметта, а не в йерархията. Трябва да го преместите в viewDidAppear

viewDidAppear()

Уведомява контролера на изгледа, че неговият изглед е добавен към йерархия на изглед. Документи на Apple

person Haagenti    schedule 18.01.2018

Както каза Sh_Khan, преместете редовете:

let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)

в метода viewDidAppear(); когато viewDidLoad() бъде извикан, контролерът на изглед все още не е добавен в йерархията на изглед, не е видим и не може да представи друг контролер на изглед.

person Rico Crescenzio    schedule 18.01.2018

Причината за такъв вид грешка е: Опитвате се да представите (отворите) два контролера за изглед едновременно (изгледът на първия представящ контролер за изглед току-що е стартиран и може да се опитвате да представите втори контролер за изглед).

Трябва да преместите своя код (за представяне/навигация на контролера за преглед) на viewDidAppear. Вашият основен изглед на съществуващ контролер за изглед (откъдето представяте нов контролер за изглед) не е готов/зареден.

Трябва да го преместите на viewDidAppear.


Ето примерен код:

Swift 4

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // instantiate your view controller either using storyboard or class or any other way....
    if let newVC = self.storyboard?.instantiateViewController(withIdentifier: "NewViewController") as? NewViewController {
         self.present(newVC, animated: true, completion: nil)
    }
}

Във вашия случай/код решението е:

override func viewDidLoad() {
    super.viewDidLoad()

     // Move your code from here (viewDidLoad) to viewDidAppear

}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // to check whether the user has already logged in or not
    Auth.auth().addStateDidChangeListener { (auth, user) in
        if user == nil {
            let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
            self.present(login, animated: true, completion: nil)
        }
    }

    print("user enter homeVC")

}

Вижте разликата между жизнения цикъл на двата контролера за преглед.

viewDidLoad

Този метод се извиква, след като контролерът на изгледа е заредил своята йерархия на изгледа в паметта. Този метод се извиква независимо дали йерархията на изгледа е заредена от nib файл или е създадена програмно в метода loadView(). Обикновено отменяте този метод, за да извършите допълнителна инициализация на изгледи, които са заредени от nib файлове.
Вижте повече за: viewDidLoad

viewDidAppear

Уведомява контролера на изгледа, че неговият изглед е добавен към йерархия на изглед.
Вижте повече за: viewDidAppear

person Krunal    schedule 18.01.2018

На този етап от вашия код изгледът на контролера на изгледа е създаден само, но не е добавен към никоя йерархия на изгледа. Ако искате да презентирате от този изглед контролер възможно най-скоро, трябва да го направите във viewDidAppear, за да сте най-безопасни.

person Muhammad Ahmad    schedule 19.07.2020