问题
I am using a UISplitViewController in my app. This works just fine on iPad where primary and secondary are always visible, and it works just fine on most iPhones where it acts like a UINavigationController.
On iPhone 6+ and 6S+ the split view acts like an iPhone in portrait and like an iPad in landscape. This splitting in landscape is causing me problems and I'd like to avoid it.
Is there any way to prevent the UISplitViewController from showing primary and secondary controllers in iPhone 6+ landscape? I just want it to show the secondary controller, the same as it would do for other iPhones.
Thanks.
回答1:
I was able to do this by subclassing the UISplitViewController and then overriding the trait collection to return a compact horizontal size class when the device is not an iPad. I know checking the interface idiom is a faux-pas these days, but I wasn't sure how else to do it.
I simply added this method to my UISplitViewController subclass:
-(UITraitCollection *)traitCollection {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return [super traitCollection];
} else {
return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
}
}
Any suggestions for a better way to do this are certainly welcome.
回答2:
Here is the same answer in Swift but also with a fix where the vertical size class would be wrong on phone in landscape:
override var traitCollection: UITraitCollection {
if UI_USER_INTERFACE_IDIOM() == .pad {
return super.traitCollection
} else {
let horizontal = UITraitCollection(horizontalSizeClass: .compact)
let vertical = UITraitCollection(verticalSizeClass: super.traitCollection.verticalSizeClass)
return UITraitCollection.init(traitsFrom: [horizontal, vertical])
}
}
回答3:
I had some issues with UINavigationControllers not displaying correctly with the code above. This is the method that worked for me (Swift 5):
1) Create a UIViewController containing a UIContainerView
2) Embed your UISplitViewController in that container
3) Add the following code:
class SplitViewContainerViewController: UIViewController {
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UI_USER_INTERFACE_IDIOM() != .pad {
performOverrideTraitCollection()
}
}
private func performOverrideTraitCollection() {
for childVC in self.children {
setOverrideTraitCollection(UITraitCollection(horizontalSizeClass: .compact), forChild: childVC)
}
}
}
4) Set the view controller containing the container view to be SplitViewContainerViewController
Update For iOS 13
The code above no longer works on iOS 13. Use the following instead on the SplitViewContainerViewController class:
override func overrideTraitCollection(forChild childViewController: UIViewController) -> UITraitCollection? {
if UIDevice.current.userInterfaceIdiom != .pad {
return UITraitCollection(horizontalSizeClass: .compact)
} else {
return super.traitCollection
}
}
来源:https://stackoverflow.com/questions/37951008/uisplitviewcontroller-prevent-splitting-in-landscape-on-iphone-6-plus