Skip to content

14 - iOS Multi MVC

Multi MVC

MVC

  • Apps usually consists of multiple views
  • Multiple MVC-s must be combined
  • One MVC acts as a VIEW for some other MVC
  • iOS provides some controllers for it
    • UITabBarController
    • UISplitViewController
    • UINavigationController
  • You can write your own (in theory…)

UITabBarController

  • Every view is separate MVC
  • UITabBarController gets its display attributes from child viewControllers var tabBarItem: UITabBarItem!
  • 5 tabs in max!

MVC

MVC

UISplitViewController

  • Two MVC-s side by side (in landscape)
    • Master
    • Detail
  • Master is hidden in portrait
    • Master will slide out from left side

MVC

UINavigationController

  • Like a stack of cards
  • New MVC is pushed on top
  • Going back destroys the topmost MVC
    • Title and backbutton info are grabbed from navigationItem from stacked MVC-s (previous and current)
  • rootViewController holds the initial View
  • toolbarItems on the bottom

MVC

Accessing sub-MVCs

  • viewController property

    1
    var viewControllers: [UIViewController]? {get set}
    

    • tabBar – in order, from left to right
    • splitView – 0 is master, 1 is detail
    • navigationController – 0 is master, rest in order of stack
  • every UIViewController knows its master (one of them is set)

1
2
3
var tabBarController: UITabBarController? { get }
var splitViewController: UISplitViewController? { get }
var navigationController: UINavigationController? { get }
  • To get the detail view from the master (in splitView)
    1
    2
    if let detail: UIViewController? = 
        splitViewController?.viewControllers[1] { ... }
    

Wiring up MVCs

  • Ctrl – Drag in storyboard!
  • Delete all extra stuff
  • Move startup pointer to correct view

MVC

MVC

  • SplitView controller only really works on iPad/iPhone+
  • Embed master view into Navigation Controller

MVC

Segues

  • When one MVC causes other MVC to appear – it’s called “SEGUE”
  • Possible segues are

    • Show Segue (push in Navigation, else Modal)
    • Show Detail Segue (shows Detail in Split or push in Navigation)
    • Modal Segue (full screen takeover, no way back)
    • Popover Segue (modal little popover window)
  • Segues always create a new instance of an MVC

  • Adding or removing MVCs from UINavigationController
    • func pushViewController(_ vc: UIViewController, animated: Bool)
    • func popViewController(animated: Bool)

Wiring segues

  • In interface builder ctrl-drag from button to some other MVC
  • Inspect the new segue and give it an Identifier (string) – used later in the code

  • Preparing for a segue

    • New MVC needs to be configured (Model and display properties)
  • Invoke segue from code (rarely used)

    1
    func performSegue(withIdentifier: String, sender: Any?)
    

Segues - naming

  • Click on segue in storyboard
  • set identifier (name for the segue)

MVC

Preparing for Segue

  • Most important func in the whole Multi MVC
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "SegueIdentifierFromStoryboard":
            if let vc = segue.destinationViewController as? SomeViewController {
                vc.someproperty = ...
                vc.setUp(...)
            }
        default: break
        }
    }
}
  • vc.someOutlet – its not set yet! Do not access any outlets!

Create Segue

  • Ctrl-drag in a storyboard from an instigator (like a button) to the MVC to segue to
  • Can be done also in code
1
2
3
4
5
6
@IBAction func Action2Clicked(_ sender: UIButton) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "Child2ViewController") as! Child2ViewController

    present(vc, animated: false, completion: nil)
}
  • Close viewcontroller (navigate back to caller)
1
2
3
4
5
6
 @IBAction func CloseClicked(_ sender: UIButton) {
    if ((self.presentingViewController) != nil){
        self.dismiss(animated: false, completion: nil)
        print("close")
    }
}

Segue - declining

Maybe you don’t want to do a segue?
Return true for segue to happen

1
2
3
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
<#code#>
}

UINavigationController

  • Set root view title in Navigation Item
  • Make segues to other MVCs
  • Set their title in ViewController Title

MVC

MVC