How can enable the masterViewController
as UISplitViewController.preferredDisplayMode (UISplitViewController.DisplayMode.PrimaryOnly)
on higher-end iPhone devices (such as iPhone 14 Plus) in landscape mode?
I am utilizing a splitView
with the style .doubleColumn
. My objective is to have the splitView
present the MasterView
as the initial screen and the DetailedView
as the subsequent screen in landscape mode, resembling the default iPhone portrait mode, specifically on higher-end iPhone devices (such as iPhone 14 Plus and iPhone Pro Max). If launched on an iPad, it should be displayed as 'side by side' ('oneBesideSecondary').
How can we display the MasterViewController using splitViewController.preferredDisplayMode
, specifically setting it to UISplitViewController.DisplayMode.PrimaryOnly
when rotated to landscape mode on iPhone higher end devices? However, it's important to note that Apple does not support UISplitViewController.DisplayMode.PrimaryOnly
.
Desired UI: iPhone Portrait:
PrimaryVC:
https://i.stack.imgur.com/cqWbH.png
secondaryVC:
https://i.stack.imgur.com/8x7Ps.jpg
iPhone Landscape:
primaryVC:
https://i.stack.imgur.com/3dCwP.png
seconddaryVC:
https://i.stack.imgur.com/bBe4O.png
iPad:
portrait:
https://i.stack.imgur.com/PfXTW.jpg
Landscape:
https://i.stack.imgur.com/teqV0.jpg
Here is my code :
class ViewController: UIViewController , UISplitViewControllerDelegate {
var splitVC = UISplitViewController(style: .doubleColumn)
var delegateProtocol : TableSelectionDelegate?
var ListView : ListViewController!
override func viewDidLoad() {
super.viewDidLoad()
splitVC.delegate = self
splitVC.presentsWithGesture = true
splitVC.preferredSplitBehavior = .tile
ListView = ListViewController()
}
override func viewWillAppear(_ animated: Bool) {
var primaryVC : ListViewController = UIStoryboard(name: "Main", bundle:nil).instantiateViewController(withIdentifier: "ListViewController") as! ListViewController
var secondVC : SecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
primaryVC.delegate = self
secondVC.view.backgroundColor = UIColor.placeholderText
if UIDevice.current.userInterfaceIdiom == .pad
{
splitVC.setViewController(primaryVC, for: .primary)
splitVC.setViewController(secondVC, for: .secondary)
splitVC.preferredDisplayMode = UISplitViewController.DisplayMode.oneBesideSecondary
}
else
{
splitVC.setViewController(secondVC, for: .primary)
splitVC.setViewController(primaryVC, for: .secondary)
splitVC.preferredDisplayMode = UISplitViewController.DisplayMode.secondaryOnly
// hide back btn to primary list
let controllers = splitVC.viewControllers
primaryVC = (controllers[controllers.count-1] as! UINavigationController).topViewController
as! ListViewController
primaryVC.navigationItem.leftBarButtonItem =
splitVC.displayModeButtonItem
primaryVC.navigationItem.leftItemsSupplementBackButton = false
}
addChild(splitVC)
splitVC.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
self.view.addSubview(splitVC.view)
splitVC.didMove(toParent: self)
}
func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) {
if UIDevice.current.userInterfaceIdiom == .phone
{
svc.presentsWithGesture = displayMode != .secondaryOnly
}
}
}
extension ViewController : TableSelectionDelegate
{
func selectedRow(row: Int, viewController: UIViewController) {
splitVC.showDetailViewController(viewController, sender: self)
}
}
I attempted the code above by swapping the PrimaryVC with .secondary
and the SecondaryVC with .primary
in the splitView for the iPhone device type. As a result, I achieved the desired UI.
splitVC.setViewController(secondVC, for: .primary)
splitVC.setViewController(primaryVC, for: .secondary)
splitVC.preferredDisplayMode = UISplitViewController.DisplayMode.secondaryOnly
However, I'm uncertain whether this approach was correct or incorrect. What would be the best approach to achieve my desired UI?