your programing

경고 :보기가 창 계층 구조에없는 *에 *를 표시하려고합니다.

lovepro 2020. 10. 15. 08:20
반응형

경고 :보기가 창 계층 구조에없는 *에 *를 표시하려고합니다.


데이터 모델에 저장된 데이터가 ViewController 있는지 여부 를 제시하려고합니다 . 하지만 다음과 같은 오류가 발생합니다.

경고 : *보기가 창 계층 구조에없는 경우에 *를 표시하려고합니다. "

관련 코드 :

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을 사용하여 찾은 다른 솔루션을 성공하지 못했습니다.


코드의이 시점에서 뷰 컨트롤러의 뷰는 생성되었을뿐 뷰 계층 구조에 추가되지 않았습니다. 가능한 한 빨리 해당 뷰 컨트롤러에서 viewDidAppear프레젠테이션하려면 가장 안전 해야합니다 .


객관적인 C에서 : 이것은 mpmovieplayer 위에 viewcontroller를 표시 할 때 내 문제를 해결했습니다.

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

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

    return topController;
}

스위프트 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

여러 스토리 보드 화면간에 전환해야하는 경우보기 컨트롤러로 조정하면됩니다.


스위프트 3.

이 함수를 호출하여 최상위 뷰 컨트롤러를 가져온 다음 해당 뷰 컨트롤러를 제공합니다.

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)

지연 시간이있는 선택기를 수행하면됩니다 (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) 
}

SWIFT 용

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
}

신속한 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}

사용자가 딥 링크를 연 후 컨트롤러를 표시하는 동안이 오류가 발생했습니다. 이것이 최선의 해결책이 아니라는 것을 알고 있지만 짧은 시간 내에 여기에 빠른 수정이 있습니다. 코드를 asyncAfter다음 같이 래핑하십시오 .

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

It will give time for your presenting controller to call viewDidAppear.


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)

This seemed to work to make sure it's the top most view.

I was getting an error

Warning: Attempt to present myapp.testController: 0x7fdd01703990 on myapp.testController: 0x7fdd01703690 whose view is not in the window hierarchy!

Hope this helps others with swift 3


I have tried so many approches! the only useful thing is:

if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
}

All implementation for topViewController here are not fully supporting cases when you have UINavigationController or UITabBarController, for those two you need a bit different handling:

For UITabBarController and UINavigationController you need a different implementation.

Here is code I'm using to get 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
    }
}

Rather than finding top view controller, one can use

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

Where viewController is the controller which you want to present This is useful when there are different kinds of views in hierarchy like TabBar, NavBar, though others seems to be correct but more sort of hackish

The other presentation style can be found on apple doc


The previous answers relate to the situation where the view controller that should present a view 1) has not been added yet to the view hierarchy, or 2) is not the top view controller.
Another possibility is that an alert should be presented while another alert is already presented, and not yet dismissed.

참고URL : https://stackoverflow.com/questions/26022756/warning-attempt-to-present-on-whose-view-is-not-in-the-window-hierarchy-s

반응형