24 - iOS Multi MVC
Multi 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 viewControllersvar tabBarItem: UITabBarItem!
- 5 tabs in max!
UISplitViewController
- Two MVC-s side by side (in landscape)
- Master
- Detail
- Master is hidden in portrait
- Master will slide out from left side
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
Accessing sub-MVCs
- viewController property
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)
var tabBarController: UITabBarController? { get }
var splitViewController: UISplitViewController? { get }
var navigationController: UINavigationController? { get }
- To get the detail view from the master (in splitView)
if let detail: UIViewController? =
splitViewController?.viewControllers[1] { ... }
Wiring up MVCs
- Ctrl – Drag in storyboard!
- Delete all extra stuff
- Move startup pointer to correct view
- SplitView controller only really works on iPad/iPhone+
- Embed master view into Navigation Controller
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)
func performSegue(withIdentifier: String, sender: Any?)
Segues - naming
- Click on segue in storyboard
- set identifier (name for the segue)
Preparing for Segue
- Most important func in the whole Multi MVC
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
@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)
@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
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