it-roy-ru.com

Предупреждение: попытка представить * на *, чье представление не находится в иерархии окон - 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)
    }
}

Я пробовал разные решения, найденные с помощью Google, но безуспешно.

74
Nils Wasell

На данный момент в вашем коде представление контроллера представления было только создано, но не добавлено ни к какой иерархии представления. Если вы хотите представить из этого контроллера представления как можно скорее, вы должны сделать это в viewDidAppear, чтобы быть максимально безопасным. 

110
Acey

В Objective C: Это решило мою проблему при представлении viewcontroller поверх mpmovieplayer

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

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

    return topController;
}
32
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

Просто настройте контроллер представления, если вам нужно переключаться между несколькими экранами раскадровки.

28
Jason

Вам просто нужно выполнить селектор с задержкой - (работает 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

Свифт 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)
12
Jacob Davis

для Свифта

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

Swift 4

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

Для 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

Я получал эту ошибку, когда представлял контроллер после того, как пользователь открыл ссылку. Я знаю, что это не лучшее решение, но если вы находитесь в сжатые сроки, вот быстрое решение - просто оберните ваш код в asyncAfter:

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

Ваш нынешний контроллер даст время для вызова viewDidAppear.

1
Bohdan Savych

Я пробовал так много подходов! единственная полезная вещь:

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, для этих двух вам нужна немного другая обработка:

Для 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
Grzegorz Krukowski

Вместо того, чтобы найти контроллер вида сверху, можно использовать

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

Где viewController - это контроллер, который вы хотите представить Это полезно, когда есть разные виды представлений в иерархии, такие как TabBar, NavBar, хотя другие выглядят правильными, но более хакерскими

Другой стиль презентации можно найти на Apple Doc

0
Akhil Dad