iOS 10/Swift:
Using SplitViewController on an iPhone the user sees the detail view when the app loads (whether in portrait or landscape both have compact width). How can you change this to load the master view on startup?
Note that when you load in a Regular Width view (ie: iPhone 6s Plus landscape) we want the Split View to continue to be shown (and not master).
You should use method
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool
which provided by UISplitViewControllerDelegate
You can define a custom UISplitViewController and assign it to your split view in the storyboard:
import UIKit
class MainSplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
return true
}
}
Related
I created an application in which I have a UISpliеViewController, also the master section has a tabbar. In the tabbar I have three controllers. When I click on the second item tabbar in portrait orientation, I have a controller called News. But when I'm in the horizontal position, I want the master section to open the controller that is on the tabbar item1, and the detail must have the News tab.
I read and think that I need to use:
func primaryViewController (forExpanding splitViewController: UISplitViewController) -> UIViewController? or
func splitViewController (_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, on primaryViewController: UIViewController) -> Pain
, but I do not understand how to organize it
I have implemented a UISplitViewController and all works fine. What I want to do is on iPhone devices only show the detailView not the masterView as the first view controller. I realise I can create a segue from the master view to the detail view in the masters viewDidLoad method however this feels a bit hacky to me. Maybe this is the only way to achieve what I want?
I have looked at the documentation for the UISplitViewControllerDelegate particularly this function however I don't feel I grasped what this actually is doing. I have also set the UISplitViewController as the delegate and set allVisible and tried all the other options in the viewDidLoad of my SplitViewController sub class
self.delegate = self
self.preferredDisplayMode = .allVisible
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
return true
}
If it helps the detailViewController heirachy in the storyboard is SplitViewController > UINavigationController > myDetailViewController
What you need to do is to use the splitviewcontroller delegate function
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool
In there you can push your second controller into your first navigation controller and return true. Returning true means that you're gonna handle the transition. e.g.
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
if let detailViewController = secondaryViewController as? YourSecondViewController, let primaryNV = primaryViewController as? UINavigationController {
primaryNV.pushViewController(detailViewController, animated: false)
returns true // I handle it myself.
}
return false // let the iOS handles it.
}
If you need more clarification, please let me know. I'll try to explain it better. cheers!.
I have a splitview with Master (showing table view) and Details (Showing detail data). When I launch my app it shows detailview first with no data but I need to show masterview first.
I know that there are some answers but nothing works for me.
Any solution?
Try this:
class MySplitViewControllerShowingMasterViewFirst: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
return true
}
}
I'm making my first universal app, so far so good, but I have a problem with UISplitViewController on iPad.
how can i make the UISplitViewController act same as on iPhone when it is in portrait mode?
like in portrait mode show only master screen when i click on it, it navigate to the details screen, and when in landscape mode show both of them beside each other.
what happens now , is that it shows the details screen only in portrait and show both of them in landscape mode.
for iPhone i used this code in master view to solve this issue
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
return true
}
but this didn't work with iPad, i found another code on here but didn't work too.
func splitViewController(svc: UISplitViewController, willHideViewController aViewController: UIViewController, withBarButtonItem barButtonItem: UIBarButtonItem, forPopoverController pc: UIPopoverController) {
self.navigationItem.leftBarButtonItem?.target?.performSelector((self.navigationItem.leftBarButtonItem?.action)!, withObject: self.navigationItem)
}
other code maybe you need to know, i added those in viewDidLoad in master view controller
self.splitViewController?.delegate = self
self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryOverlay
self.splitViewController!.maximumPrimaryColumnWidth = splitViewController!.view.bounds.size.width;
self.splitViewController!.preferredPrimaryColumnWidthFraction = 0.3
so please if anyone can help me find solution for this issue, I will be very thankful
UISplitViewController use size classes to determine how to display his master and detail view controller.
When your UISplitViewController has horizontalSizeClass and verticalSizeClass Regular it will display both the Master and Detail view controllers on the same screen.
You'll need to embed your split view controller into a container view controller to override the default size class as I explained here.
You also have to check the device orientation to fork between Compact (when Portrait) or Regular (when Landscape) horizontal size class:
class ContainerVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
performOverrideTraitCollection()
}
private func performOverrideTraitCollection() {
let orientation = UIDevice.currentDevice().orientation
var isPortrait = false
switch orientation {
case .Portrait, .PortraitUpsideDown:
isPortrait = true
default:
isPortrait = false
}
for childVC in self.childViewControllers {
self.traitCollection.userInterfaceIdiom
setOverrideTraitCollection(UITraitCollection(horizontalSizeClass: isPortrait ? .Compact : .Regular), forChildViewController: childVC)
}
}
}
I tried to implement UISplitViewController by following steps in 《iOS 8 by tutorial》。
The ducoment said if I return yes in splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: method, the split view controller will shows only the content from its primary view controller.
But in my project, the split view controller shows both primary and secondary view controller in collapsed interface no matter I return true of false in this method. And the most wired thing is that this method is only called once when the app begins running.
Here is my custom SplitViewController which subclasses to UISplitViewController:
import UIKit
class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
// MARK:- UISplitViewControllerDelegate
func splitViewController(splitController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
// We don't want anything to happen. Say we've dealt with it
return true
}
}
I found I needed to add "self.preferredDisplayMode=.primaryOverlay" to my ViewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.delegate = self
self.preferredDisplayMode = .primaryOverlay
}
The preferredDisplayMode has some other options to customize the initial behavior you can toy with to get your preferred look and feel.
Note this is for iPhone, Compact Width. Test also on an iPad as it behaves differently (landscape vs. portrait).