source

경고:창 계층 구조에 없는 *에 * 표시 시도 - swift

ittop 2023. 9. 4. 20:39
반응형

경고:창 계층 구조에 없는 *에 * 표시 시도 - swift

제가 발표하려고 하는 것은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)
    }
}

저는 구글을 사용하여 찾은 다양한 솔루션을 시도했지만 성공하지 못했습니다.

현재 코드에서 보기 컨트롤러의 보기는 작성되었을 뿐 보기 계층 구조에는 추가되지 않았습니다.가능한 한 빨리 해당 뷰 컨트롤러에서 표시하려면 에서 표시해야 합니다.viewDidAppear가장 안전하게.

목표 c: mpmovie 플레이어 위에 뷰 컨트롤러를 표시할 때의 문제를 해결했습니다.

- (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)

내 탭 컨트롤러에서 대신 사용:

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)

SWIFT용

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

지연이 발생한 셀렉터만 수행하면 됩니다(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) 
}

스위프트 4

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

메인 스레드를 사용하여 뷰 컨트롤러를 표시하거나 해제하는 것이 저에게 효과가 있었습니다.

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

사용자가 딥 링크를 연 후 컨트롤러를 제시하는 동안 이 오류가 발생했습니다.이것이 최선의 해결책이 아니라는 것을 알지만, 만약 당신이 짧은 시간 안에 있다면 여기에 빠른 해결책이 있습니다 - 코드를 랩으로 감으세요.asyncAfter:

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

프레젠테이션 컨트롤러가 전화를 걸 시간을 줍니다.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)

이것은 그것이 가장 높은 뷰를 확실히 하기 위해 효과가 있는 것처럼 보였습니다.

오류가 발생했습니다.

경고:myapp.testController: 0x7fdd01703990을 myapp.testController: 0x7fd01703690의 보기가 창 계층에 없습니다!

이것이 빠른 3으로 다른 사람들에게 도움이 되기를 바랍니다.

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

Swift 5.1:

let storyboard = UIStoryboard.init(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(withIdentifier: "ID")
let appDeleg = UIApplication.shared.delegate as! AppDelegate
let root = appDeleg.window?.rootViewController as! UINavigationController
root.pushViewController(mainViewController, animated: true)

나는 많은 접근법을 시도해 왔습니다! 유일하게 유용한 것은:

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

여기 topViewController에 대한 모든 구현이 다음과 같은 경우를 완전히 지원하지는 않습니다.UINavigationController또는UITabBarController이 두 가지의 경우 약간 다른 처리가 필요합니다.

위해서UITabBarController그리고.UINavigationController다른 구현이 필요합니다.

다음은 상위 MostViewController를 가져오는 데 사용하는 코드입니다.

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) 보기를 제공해야 하는 보기 컨트롤러가 아직 보기 계층에 추가되지 않았거나 2) 보기 컨트롤러가 최상위 보기 컨트롤러가 아닌 상황과 관련이 있습니다.
또 다른 가능성은 다른 경고가 이미 표시되어 있고 아직 해제되지 않은 상태에서 경고를 표시해야 한다는 것입니다.

Swift Method(Swift Method), 데모를 제공합니다.

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

func demo() {
    let vc = ViewController()
    let nav = UINavigationController.init(rootViewController: vc)
    topMostController().present(nav, animated: true, completion: nil)
}

Top View 컨트롤러를 찾는 대신 사용할 수 있습니다.

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

viewController가 표시할 컨트롤러인 경우 탭바, NavBar와 같은 계층 구조에 다른 종류의 보기가 있을 때 유용합니다. 다른 보기는 올바르지만 좀 더 해커적입니다.

다른 프레젠테이션 스타일은 애플 문서에서 찾을 수 있습니다.

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

반응형