Group Group Group Group Group Group Group Group Group

raywenderlich.com Forums

UISplitViewController Tutorial: Getting Started

Learn how to split your iOS app into two sections and display a view controller on each side in this UISplitViewController tutorial.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/265-uisplitviewcontroller-tutorial-getting-started

Excellent Tutorial as usual. I think it stops one step short of a complete solution. That is on the smaller format devices the app opens up at the detail view level not with the list view (master view) as most apps do. Changing a few attributes in the SplitViewController can change this behaviour to showing master view first. Create this custom SplitViewController as shown below and select it in the storyboard as the Custom Class for the SplitViewController.

class PrimarySplitViewController: UISplitViewController,
                              UISplitViewControllerDelegate {

override func viewDidLoad() {
    self.delegate = self
    self.preferredDisplayMode = .allVisible
}

func splitViewController(
         _ splitViewController: UISplitViewController,
         collapseSecondary secondaryViewController: UIViewController,
         onto primaryViewController: UIViewController) -> Bool {
    // Return true to prevent UIKit from applying its default behavior
    return true 
}
}

More details in this SO Answer:

1 Like

Excellent point and thank your sharing that snippet! For the tutorial I wanted to keep it with the default behavior, but you are absolutely right that most apps prefer the way you suggest. I too think that makes a nicer experience for the user.

Hey @mkatz,

First of all, great tutorial :slight_smile:
I am currently working on an app that has a couple of screens before it needs to use a split view controller.
How do I approach that, since, by the Apple standards, a UISplitViewController should always be the root view controller, and in my case I don’t think that is possible.
Would container view controllers be the solution here?
I would really appreciate your opinion on this.

Thank you in advance :slight_smile:

@mkatz I’m in a similar situation. Looking at an iPad app that can have a multi-tier UISplitViewController similar to Ulysses where there’s a second tier tableview between the root tableview and the detail. I’ve tried modifying the segues between objects, but having little luck in getting it work correctly.

Any ideas welcome!

@mkatz Can you please help with this when you get a chance? Thank you - much appreciated! :]

This is a little tricky, since Apple’s guidance is confusing which leads to muddy expectations of how to use it beyond the actual root controller. I think it’s fine to show a splitview controller as the main VC in a tab or presented modally. I’m not suprised it doesn’t work when pushing it on to a navigation stack since I think that would be a nightmare from a navigation and wayfinding perspective.

I haven’t used Ulysses so I am not sure how they do it, but it maybe a modal with a custom transition animation?

1 Like

Great tutorial! There’s only one issue that I’m having. After following all the instructions, the detail view is still unable to show the name, description, and the images from the array. It only shows the labels that I created with the original text I assigned to them (“Monster Name” and “Description”). Do you have any idea why this could be?

@mkatz Can you please help with this when you get a chance? Thank you - much appreciated! :]

are the labels connected as outlets? Double check this step:

Now, go open up Main.storyboard. Right-click the Detail View Controller object from the Document Outline to display the list of outlets. Drag from the circle at the right of each item to the view to hook up the outlets.

Ok good one. Now how would one insert a LoginVC before the MasterVC? My app runs starting with a Navigation Controller–>Facebook LoginVC–>MainVC setup. The MainVC does not need to be any wider than iPhone Plus in portrait. However just adding a UISplitView–>NavController–>Facebook LoginVC–>MasterVC: (1) No longer logs in correctly in portrait: the < logout button appears at the top of a blank screen, tapping it goes back to the correct login view, after which the thing acts right as before. (2) In iPhone plus landscape it logs in correctly in the left masterVC. (3) In iPad nothing shows in portrait, and no login button in landscape.

Since just about every app requires a Login … can’t help but think a LoginVC placeholder should be part of the UISplitViewController object. Yet another radical idea I guess.

I don’t quite follow the description, but I think this is why a lot of apps put the login VC in a modal so it escapes the basic hierarchy.

As to why there is a blank view, I would double check what the selected item is in the master vc, and if it is as expected, it might be an ordering of when the detail view gets set-up.

Thanks for the reply. Yes converting my Login VC to modal appears to best, maybe only, way to go on my app. So my description is the same as your image above shown after: “This will add several elements to your storyboard:” wherein I take it I can leave the storyboard Navigation Controller–>Root Master View Controller relationship – and then maybe in the AppDelegate and VC files programmically modally “push” or “present” i.e. interject the LoginVC?

“As to why there is a blank view, I would double check what the selected item is in the master vc”

Turns out if I swipe left to right the LoginVC appears, which needs to show however without swiping. Then when I login in the iPad a blank screen where “< Back” button appears, which slides in the MasterVC. Maybe when I get the LoginVC coded modally that will clear up. Also, hopefully still relevant to your excellent tutorial, in my case on the iPhone Plus the SplitView is not a good UI, so I need to somehow apply SplitView to iPad only.

Ok nothing is selected in MasterVC to show in DetailVC – since in every case the UIButtons in MasterVC open up a new full-screen Safari URL – when selected on the IPad preferrably open up Safari URL in DetailVC.

@mkatz Do you have any feedback regarding this? Thank you - much appreciated! :]

Hello, nice tutorial, thank you. I have some doubts, in my opinion UISplitViewController is nice for and iPad device, but for iPhone is ugly or doesn’t give the user a good experience. I am developing an application where the main UI is TabBarController (for iPhone), it looks nice on different iPhone devices, but when I decided to give the iPad user experience a UISplitViewController is the way to go, I am doing all programmatically (No Storyboards), my question is how can I detect the device type or screen and to show a different UI accordingly (UISplitViewController for iPads and UITabBar for iPhones)?

Could you please help me with some suggestions about it?

Makes sense. UISplitViewController is made to be able to do the different nav styles based on device, but you want to make the best user experience, so sometimes it makes sense to have different navigation stacks altogether. You can detect device type using UIDevice.userInterfaceIdiom https://developer.apple.com/documentation/uikit/uidevice/1620037-userinterfaceidiom

Wow, quick response, today is my lucky day (thank you). Thank you very much.

Reading the documentation…

Edited : Newb found it. Not sure if restarting Xcode helped or drinking enough coffee to wake up did it. shrugs

Something seems to have changed in Xcode as it relates to certain steps in the section titled “Creating Custom ViewControllers”. The steps in question detail how to change the “class” of a storyboard RootViewController via the identity inspector.

The steps to change the class of Main.Storyboard says to:

  1. Open Main.storyboard .
  2. Select the Root View Controller .
  3. Click on the Identity inspector .
  4. Change the class to MasterViewController . <–There is the problem. No “class”…lol.

There just does not seem to be any “Class” Field in the identity inspector for Main.Storyboard.
???

Does anyone know what I am missing?

Note: steps referenced are located just after the following text copy :
“This way, you’ll just have 10 empty rows to look at when you test this thing out later.” …

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!