From dcc8f38f3d5d62fa2a48dcccdadacbca090bb478 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 10 Oct 2022 18:56:27 -0400 Subject: [PATCH] Fix key commands not working inside split nav controller on iPad Fixes #179 --- .../Main/MainSplitViewController.swift | 5 --- .../Utilities/SplitNavigationController.swift | 43 ++++++++++++------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Tusker/Screens/Main/MainSplitViewController.swift b/Tusker/Screens/Main/MainSplitViewController.swift index 0461e8dd7d..1fc9e74241 100644 --- a/Tusker/Screens/Main/MainSplitViewController.swift +++ b/Tusker/Screens/Main/MainSplitViewController.swift @@ -20,9 +20,6 @@ class MainSplitViewController: UISplitViewController { private var tabBarViewController: MainTabBarViewController! -// private var secondaryNavController: UINavigationController! { -// viewController(for: .secondary) as? UINavigationController -// } private var secondaryNavController: SplitNavigationController! { viewController(for: .secondary) as? SplitNavigationController } @@ -49,8 +46,6 @@ class MainSplitViewController: UISplitViewController { setViewController(sidebar, for: .primary) primaryBackgroundStyle = .sidebar -// let secondaryNav = EnhancedNavigationViewController() -// secondaryNav.useBrowserStyleNavigation = true let splitNav = SplitNavigationController() setViewController(splitNav, for: .secondary) // don't unnecesarily construct a content VC unless the we're in actually split mode diff --git a/Tusker/Screens/Utilities/SplitNavigationController.swift b/Tusker/Screens/Utilities/SplitNavigationController.swift index d916c220c5..cf7926d388 100644 --- a/Tusker/Screens/Utilities/SplitNavigationController.swift +++ b/Tusker/Screens/Utilities/SplitNavigationController.swift @@ -60,6 +60,7 @@ class SplitNavigationController: UIViewController { self.rootNav.pushViewController(vc, animated: true) } } + secondaryNav.owner = self secondaryNav.closeSecondaryImpl = { [unowned self] in self.popToRootViewController(animated: true) } @@ -72,26 +73,19 @@ class SplitNavigationController: UIViewController { // it needs a UINavigationController to be this VC's first child, otherwise it will embed this VC inside // yet another UINavigationController, which can then cause a crash when we try to embed a nav controller inside // of ourself (because nested nav controllers are forbidden) - rootNav.willMove(toParent: self) - addChild(rootNav) - rootNav.didMove(toParent: self) - secondaryNav.willMove(toParent: self) - addChild(secondaryNav) - secondaryNav.didMove(toParent: self) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() + // and because of that, the view needs to be added here, in between the addChild/didMove(toParent:) calls + // and so the view needs to be loaded immediately + loadViewIfNeeded() + addChild(rootNav) rootNav.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(rootNav.view) + rootNav.didMove(toParent: self) + addChild(secondaryNav) secondaryNav.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(secondaryNav.view) - + secondaryNav.didMove(toParent: self) + separatorView.backgroundColor = .separator separatorView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(separatorView) @@ -110,10 +104,20 @@ class SplitNavigationController: UIViewController { secondaryNav.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), secondaryNav.view.leadingAnchor.constraint(equalTo: separatorView.trailingAnchor), ]) - + updateSecondaryNavVisibility() } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + // NOTE: as explained by the large comment above, viewDidLoad is called during initialization, and so things may not be fully setup when it is + } + override func show(_ vc: UIViewController, sender: Any?) { if !canShowSecondaryNav { rootNav.pushViewController(vc, animated: true) @@ -247,6 +251,7 @@ private class SplitRootNavigationController: UINavigationController { } private class SplitSecondaryNavigationController: EnhancedNavigationViewController { + fileprivate unowned var owner: SplitNavigationController! fileprivate var closeSecondaryImpl: (() -> Void)! override var viewControllers: [UIViewController] { @@ -257,6 +262,12 @@ private class SplitSecondaryNavigationController: EnhancedNavigationViewControll } } + override var next: UIResponder? { + // ordinarily, the next responder in the chain would be the SplitNavigationController's view + // but that would bypass the VC in the root nav, so we reroute the repsonder chain to include it + owner.viewControllers.first!.view + } + private func configureSecondarySplitCloseButton(for viewController: UIViewController) { guard viewController.navigationItem.leftBarButtonItem?.tag != ViewTags.splitNavCloseSecondaryButton else { return