web-dev-qa-db-ja.com

警告:ビューがウィンドウ階層にない* on *を表示しようとしています-swift

ViewControllerを提示しようとしていますifデータモデルに保存されたデータがあります。しかし、次のエラーが表示されます。

警告:*ビューがウィンドウ階層にない*に*を表示しようとしています

関連コード:

override func viewDidLoad() {
    super.viewDidLoad()
    loginButton.backgroundColor = UIColor.orangeColor()

    var request = NSFetchRequest(entityName: "UserData")
    request.returnsObjectsAsFaults = false

    var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    var context:NSManagedObjectContext = appDel.managedObjectContext!

    var results:NSArray = context.executeFetchRequest(request, error: nil)!

    if(results.count <= 0){
        print("Inga resultat")
    } else {
        print("SWITCH VIEW PLOX")
        let internVC = self.storyboard?.instantiateViewControllerWithIdentifier("internVC") as internViewController
        self.presentViewController(internVC, animated: true, completion: nil)
    }
}

Googleを使用して見つかったさまざまなソリューションを試してみましたが成功しませんでした。

75
Nils Wasell

コードのこの時点では、View Controllerのビューは作成されているだけで、ビュー階層には追加されていません。できるだけ早くそのView Controllerから表示したい場合は、viewDidAppearで最も安全にする必要があります。

115
Acey

目的C:mpmovieplayerの上にViewControllerを表示するときの問題を解決しました

- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}
33
akr ios

スイフト3

私はこれを初心者として続けており、現在のロードモーダルビューは閉じることができますが、モーダルを表示する必要がない場合はルートコントローラーに切り替えるのが最適です。

私はこれを使用していました

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc  = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController
present(vc, animated: false, completion: nil)

私のtabControllerでこれを代わりに使用:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let view = storyboard.instantiateViewController(withIdentifier: "MainAppStoryboard") as UIViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//show window
appDelegate.window?.rootViewController = view

複数のストーリーボード画面を切り替える必要がある場合は、View Controllerに合わせて調整してください。

31
Jason

スウィフト3。

この関数を呼び出して、最上位のView Controllerを取得し、そのView Controllerを存在させます。

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
        while (topController.presentedViewController != nil) {
            topController = topController.presentedViewController!
        }
        return topController
    }

使用法:

let topVC = topMostController()
let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController
topVC.present(vcToPresent, animated: true, completion: nil)
13
Jacob Davis

セレクターを遅延して実行する必要があります-(0秒が機能します)。

override func viewDidLoad() {
    super.viewDidLoad()
    perform(#selector(presentExampleController), with: nil, afterDelay: 0)
}

@objc private func presentExampleController() {
    let exampleStoryboard = UIStoryboard(named: "example", bundle: nil)
    let exampleVC = storyboard.instantiateViewController(withIdentifier: "ExampleVC") as! ExampleVC
    present(exampleVC, animated: true) 
}
13
Edward

スイフト用

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

スイフト4

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}
5
Allen Wixted

ユーザーがディープリンクを開いた後、コントローラーを表示しているときにこのエラーが発生しました。私はこれが最善の解決策ではないことを知っていますが、あなたが短い時間枠にいるなら、ここに簡単な修正があります-コードをasyncAfterでラップするだけです:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: { [weak self] in
                                navigationController.present(signInCoordinator.baseController, animated: animated, completion: completion)
                            })

提示するコントローラーがviewDidAppearを呼び出す時間を与えます。

2
Bohdan Savych

Swift 3.0以降の場合

public static func getTopViewController() -> UIViewController?{
if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
  return topController
}
return nil}
2
Hiren Panchal

私は非常に多くのアプローチを試みました!唯一の有用なことは:

if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
}
1
Xiaohan Chen
let storyboard = UIStoryboard(name: "test", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "teststoryboard") as UIViewController
UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)

これは、最上位のビューであることを確認するために機能するように見えました。

エラーが発生しました

警告:myapp.testControllerで0x7fdd01703990を表示しようとしています:myapp.testController:0x7fdd01703690のビューはウィンドウ階層にありません!

これがSwift 3で他の人を助けることを願っています

1
Jason

ここでのtopViewControllerのすべての実装は、UINavigationControllerまたはUITabBarControllerがある場合を完全にサポートするわけではありません。これら2つの場合、少し異なる処理が必要です。

UITabBarControllerおよびUINavigationControllerには、別の実装が必要です。

TopMostViewControllerを取得するために使用しているコードは次のとおりです。

protocol TopUIViewController {
    func topUIViewController() -> UIViewController?
}

extension UIWindow : TopUIViewController {
    func topUIViewController() -> UIViewController? {
        if let rootViewController = self.rootViewController {
            return self.recursiveTopUIViewController(from: rootViewController)
        }

        return nil
    }

    private func recursiveTopUIViewController(from: UIViewController?) -> UIViewController? {
        if let topVC = from?.topUIViewController() { return recursiveTopUIViewController(from: topVC) ?? from }
        return from
    }
}

extension UIViewController : TopUIViewController {
    @objc open func topUIViewController() -> UIViewController? {
        return self.presentedViewController
    }
}

extension UINavigationController {
    override open func topUIViewController() -> UIViewController? {
        return self.visibleViewController
    }
}

extension UITabBarController {
    override open func topUIViewController() -> UIViewController? {
        return self.selectedViewController ?? presentedViewController
    }
}
1

トップビューコントローラーを見つけるのではなく、使用することができます

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

ViewControllerは表示するコントローラーです。これは、TabBar、NavBarなどの階層にさまざまな種類のビューがある場合に便利です。

他の表示スタイルは Apple doc にあります

0
Akhil Dad

これまでの回答は、ビューを表示するView Controllerが1)View階層にまだ追加されていない、または2)Top View Controllerではない状況に関連しています。
別の可能性は、別のアラートがすでに表示されているときにアラートを表示する必要があり、まだ却下されていないことです。

0