iOS

⌘K
  1. Home
  2. Docs
  3. iOS
  4. UI Container Controllers
  5. UISplitViewController

UISplitViewController

What is UISplitViewController?

UISplitViewController is a specialized UIViewController used for displaying two view controllers side-by-side in a master-detail layout. It is commonly used in iPad applications and adapts dynamically to different screen sizes.


1. Key Features of UISplitViewController

Master-Detail Interface – Shows two view controllers at once.
Adaptive Layout – Automatically adjusts for different devices (iPhone/iPad).
Automatic Collapsing – Collapses into a single view on smaller screens.
Built-in Navigation Support – Easily integrates with UINavigationController.
Customizable Display Modes – Supports .automatic, .primaryOverlay, .secondaryOnly, etc.


2. Creating a UISplitViewController

You can set up a UISplitViewController in two ways:

  • Using Storyboard
  • Programmatically

2.1 Using Storyboard

  1. Drag a UISplitViewController onto the canvas.
  2. Assign a MasterViewController (left panel) and DetailViewController (right panel).
  3. Embed both in UINavigationController (recommended).
  4. Set UISplitViewController as the initial view controller.

2.2 Creating UISplitViewController Programmatically

import UIKit

class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        let masterVC = UINavigationController(rootViewController: MasterViewController())
        let detailVC = UINavigationController(rootViewController: DetailViewController())

        self.viewControllers = [masterVC, detailVC]
        self.delegate = self
        self.preferredDisplayMode = .oneBesideSecondary  // Controls layout behavior
    }
}

This sets up a basic Split View with a Master and Detail view.


3. UISplitViewController Display Modes

UISplitViewController has different display modes that define how views appear:

ModeDescription
.automaticAutomatically chooses the best mode based on the device.
.oneBesideSecondaryShows master and detail side-by-side (default for iPads).
.oneOverSecondaryOverlays master view over the detail view.
.oneOverPrimaryOverlays detail view over master (useful for compact layouts).
.secondaryOnlyHides the master and shows only the detail.

Example: Setting Display Mode

self.preferredDisplayMode = .oneBesideSecondary

4. Handling View Collapsing on Small Screens

By default, UISplitViewController collapses into a single view on iPhones. To handle this, implement the collapseSecondaryViewController delegate method.

func splitViewController(
    _ splitViewController: UISplitViewController,
    collapseSecondary secondaryViewController: UIViewController, 
    onto primaryViewController: UIViewController) -> Bool {
    
    return true  // Returns true to collapse the detail view into the master view
}

This ensures the detail view does not open separately on small screens.


5. Passing Data Between Master and Detail

5.1 Using Delegates

  1. Create a Protocol in MasterViewController
protocol MasterViewControllerDelegate: AnyObject {
    func didSelectItem(_ item: String)
}
  1. Implement Protocol in DetailViewController
class DetailViewController: UIViewController, MasterViewControllerDelegate {
    let detailLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupLabel()
    }

    func setupLabel() {
        detailLabel.frame = CGRect(x: 50, y: 100, width: 300, height: 50)
        view.addSubview(detailLabel)
    }

    func didSelectItem(_ item: String) {
        detailLabel.text = "Selected: \(item)"
    }
}
  1. Set Delegate in SplitViewController
if let masterNav = viewControllers.first as? UINavigationController,
   let masterVC = masterNav.viewControllers.first as? MasterViewController,
   let detailVC = (viewControllers.last as? UINavigationController)?.viewControllers.first as? DetailViewController {
    
    masterVC.delegate = detailVC
}

This allows the MasterViewController to send data to DetailViewController.


6. Example: Complete UISplitViewController Implementation

import UIKit

class MasterViewController: UITableViewController {
    weak var delegate: MasterViewControllerDelegate?
    let items = ["Item 1", "Item 2", "Item 3"]

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Master"
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        delegate?.didSelectItem(items[indexPath.row])
    }
}

class DetailViewController: UIViewController, MasterViewControllerDelegate {
    let detailLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupLabel()
    }

    func setupLabel() {
        detailLabel.frame = CGRect(x: 50, y: 100, width: 300, height: 50)
        view.addSubview(detailLabel)
    }

    func didSelectItem(_ item: String) {
        detailLabel.text = "Selected: \(item)"
    }
}

class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        let masterVC = UINavigationController(rootViewController: MasterViewController())
        let detailVC = UINavigationController(rootViewController: DetailViewController())

        self.viewControllers = [masterVC, detailVC]
        self.delegate = self
        self.preferredDisplayMode = .oneBesideSecondary

        if let master = masterVC.viewControllers.first as? MasterViewController,
           let detail = detailVC.viewControllers.first as? DetailViewController {
            master.delegate = detail
        }
    }
}

// Setting SplitViewController as the root in SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = SplitViewController()
        window?.makeKeyAndVisible()
    }
}

This creates a functional UISplitViewController with a Master-Detail interface!


7. Summary

✔️ UISplitViewController is ideal for iPad apps and works with adaptive layouts.
✔️ Supports multiple display modes for better user experience.
✔️ Automatically collapses on smaller screens like iPhones.
✔️ Uses delegates or NotificationCenter to pass data between Master and Detail views.

Would you like help with customizing animations or transitions in UISplitViewController? 🚀