Reputation: 465
So my use-case is that I have a TabBarController
in the detailview, and around four tabs each with its own NavigationController
. All are via storyboard. Then on my App Delegate
I have this:
let splitViewController = self.window!.rootViewController as! UISplitViewController
splitViewController.preferredDisplayMode = .allVisible
let tabBarController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UITabBarController
for item in tabBarController.viewControllers!{
let navigationController = item as! UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
}
And so I have a Button
on each NavigationController
. The issue is at first when I use the button on the first tab, it works fine, but as soon as I move tabs, when I return to the previous tabs and use the button, it disappears. Then, when I switch to another tab, it goes back. Surprisingly, this doesn't happen on the last tab. I've tried to search for a solution but I can't find any. And so I'm in a slump right now.
I added a gif to show the behavior.
EDIT: I don't know if this matters, but this project is landscape-only.
Upvotes: 2
Views: 1023
Reputation: 465
I'll add an answer as an additional information per the official support from Apple, in case anyone wonders:
"UISplitViewController’s displayModeButtonItem can only reside in one place in the view hierarchy at a time, not in multiple places or multiple view controllers. Currently you are pointing it to all the view controllers in the tabbar. Doing so yields unpredictable results as we have seen."
The accepted answer, though quite a hacky workaround, works. Apple's support recommendation though, is work on it in the TabBarController level.
Upvotes: 3
Reputation: 523
I believe this is a UIKit bug. Behavior actually depends on the order of view controllers, on which you set navigationItem.leftBarButtonItem
. The bug will start reproducing after view of the last one of them will be loaded.
There is a hacky workaround though. Add this to the object, which implements UISplitViewControllerDelegate
of your UISplitViewController
func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewControllerDisplayMode) {
DispatchQueue.main.async {
let tabBarController = svc.viewControllers.last as! UITabBarController
let navigationController = tabBarController.selectedViewController as! UINavigationController
navigationController.viewControllers.first?.navigationItem.leftBarButtonItem = nil
navigationController.viewControllers.first?.navigationItem.leftBarButtonItem = svc.displayModeButtonItem
}
}
It will work without DispatchQueue.main.async
, but leftBarButtonItem
's position would be wrong for some reason, and I don't know a way to update it's layout.
Hope it helps.
Upvotes: 2