web-dev-qa-db-ja.com

Swift 4ビューがウィンドウ階層にないViewControllerを提示しようとします

使っています Swift 4alertViewを使用してユーザーをサインアップしているときにエラーが発生した場合、Firebaseを作成しようとしています。サインアップボタンにIBActionがあります。これは、2つのtextfieldsからのテキストを使用してユーザーをサインアップします。1つは電子メール用、もう1つはパスワード用です。

基本的に、サインアッププロセスでエラーが発生した場合、たとえば空のalertviewがある場合にtextfieldを表示しようとしています。

enter image description here

関数のスクリーンショットを、それが発生している場所に添付しました。印刷ステートメントにエラーがあるとエラーが出力されるため、実際にエラーが発生していることはわかっています。

エラーの有無に関係なく、アラートビューは表示されず、アプリは関係なくセグエを実行します。

2019-01-15 21:40:26.368924-0500 Pronto [9036:225268]警告:ビューがウィンドウ階層にない場合に表示しようとしています

これは、現在表示されているアラートビューで取得している出力です。私はこれと同じ問題に関する他のすべての投稿を見てきましたが、どれも機能していないようです。

3

この問題は、ビューの階層が原因で発生します。

ビュー階層内のCurrent/Topmostビューコントローラを見つけて、アラートを表示する必要があります。

最上位のView Controllerを見つけるには、次のコードを使用します:

func getTopMostViewController() -> UIViewController? {
    var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

    while let presentedViewController = topMostViewController?.presentedViewController {
        topMostViewController = presentedViewController
    }

    return topMostViewController
}

そして、最上位のビューコントローラー上にアラートを表示し、メインスレッドを使用してアラートを表示します。クロージャーが別のスレッドで動作している可能性があるためです。

DispatchQueue.main.async { 
    getTopMostViewController()?.present(alertController, animated: true, completion: nil)
}

このスタックの回答を参照してください: Swift 3ウィンドウ階層にないビューを表示しようとします

18

ViewがLoadの代わりにViewDidAppearを使用してみてください。

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

    let alertViewController = UIAlertController(title: "Any", message: "Any Custom Message", preferredStyle: .alert)

    alertController.addAction(UIAlertAction(title: "ANy", style: .cancel, handler: nil))
    present(alertViewController, animated: true, completion: nil)
}
1
Mayank Wadhwa

最上位のビューコントローラーを取得し、そのビューコントローラーにアラートを表示させることができます。したがって、self.presentの代わりにこのアプローチを使用して、機能するかどうかを確認します。

let topViewController = UIApplication.shared.keyWindow?.rootViewController
topViewController?.present(alertController, animated: true, completion: nil)

また、createUser完了ハンドラーでアラートを表示しようとしているので、メインスレッドで提示してみてください。

DispatchQueue.main.async { 
    self.present(alertController, animated: true, completion: nil)
}