UINavigationController внутри UITabBarController внутри UISplitViewController (все еще) показывает детальный контроллер модально вместо нажатия - PullRequest
2 голосов
/ 19 апреля 2019

У меня есть то, что кажется очень распространенной настройкой в ​​моем универсальном приложении, с корнем UISplitViewController, использующим UITabBarController в качестве masterViewController, и затем я хочу:

  • либо поместите контроллер подробного просмотра в стек, если я нахожусь на вертикальном iPhone
  • покажите подробный контроллер в detailViewController UISplitViewController на iPhone 6+ lanscape и других больших экранах, таких как iPad и т.п.

Для этого у меня точно такая же настройка, как и во всех тех обсуждениях, в которых упоминается похожая проблема:

Но ни одно из решений, упомянутых в этих вопросах, не работает.Некоторые из них создают бесконечный рекурсивный цикл и EXC_BAD_ACCESS.И последний, который я попробовал, просто продолжает представлять контроллер детального представления модально, а не помещать его в стек на iPhone.Я создал собственный подкласс UISplitViewController следующим образом:

    class RootSplitViewController: UISplitViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            self.delegate = self
        }
    }

    extension RootSplitViewController: UISplitViewControllerDelegate {
        func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
            if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
                if(splitViewController.traitCollection.horizontalSizeClass == .compact) {
                    tabController.selectedViewController?.show(vc, sender: sender)
                } else {
                    splitViewController.viewControllers = [tabController, vc]
                }
            }

            return true
        }

        func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? {
            if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
                if let navController = tabController.selectedViewController as? UINavigationController {
                    return navController.popViewController(animated: false)
                } else {
                    return nil
                }
            } else {
                return nil
            }
        }
    }

А вот код в главном контроллере представления для отображения контроллера подробного представления:

self.performSegue(withIdentifier: "showReference", sender: ["tags": tags, "reference": reference])

Гдеtags и reference, где загружены из Firebase.И, конечно, sege showReference имеет вид «Show Detail (например, Replace)».

Первый метод делегата вызывается правильно, о чем свидетельствует точка останова, которая попадает туда, когда я щелкаю элемент всписок внутри UITabBarController.И все же контроллер подробного представления все еще представлен модально на iPhone.Однако на iPad проблем нет: контроллер детального просмотра отображается справа, как и ожидалось.

Большинство упомянутых выше ответов довольно старые, и некоторые решения реализованы в Objective-C, поэтому, возможно, я сделал что-то не такв преобразовании, или что-то изменилось в реализации UISplitViewController с тех пор.

У кого-нибудь есть предложения?

Ответы [ 2 ]

2 голосов
/ 23 апреля 2019

Я понял это. Фактически, это было связано с целевым контроллером представления, который я пытался показать. Из 2 методов, которые я переопределил в UISplitViewControllerDelegate, был назван только первый:

func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
    if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
        if(splitViewController.traitCollection.horizontalSizeClass == .compact) {
            tabController.selectedViewController?.show(vc, sender: sender)
        } else {
            splitViewController.viewControllers = [tabController, vc]
        }
    }

    return true
}

Но контроллер представления, который я показывал в первой ветви теста, уже был встроен в UINavigationController, поэтому я, по сути, показывал UINavigationController в другой, и в этом случае модал имел больше смысла. Поэтому в этом случае мне нужно было показать контроллер вида сверху UINavigationController, что, как я полагаю, было целью второго метода, который я переопределяю в делегате, но он никогда не вызывался. Так что я сделал это прямо со следующей реализацией:

extension RootSplitViewController: UISplitViewControllerDelegate {
    func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
        if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
            if(splitViewController.traitCollection.horizontalSizeClass == .compact) {
                if let navController = vc as? UINavigationController, let actualVc = navController.topViewController {
                    tabController.selectedViewController?.show(actualVc, sender: sender)
                    navController.popViewController(animated: false)
                } else {
                    tabController.selectedViewController?.show(vc, sender: sender)
                }
            } else {
                splitViewController.viewControllers = [tabController, vc]
            }
        }

        return true
    }
}

И это, кажется, прекрасно работает как на iPhone, так и на iPad

0 голосов
/ 23 апреля 2019

После того, как вы попробовали метод ShowDetailViewController, чтобы изменить контроллер подробного вида в контроллере разделенного представления.

splitViewController.showDetailViewController(vc, sender: self)

Если в случае, если ваш контроллер вида не содержит контроллер навигации, вы также можете встроить его в контроллер навигации.

 let nav = UINavigationController.init(rootViewController: vc)
 splitViewController.showDetailViewController(nav, sender: self)
...