{"id":15874620,"url":"https://github.com/rudifa/ios-customcontainerviewcontroller","last_synced_at":"2025-04-01T23:21:37.449Z","repository":{"id":74524015,"uuid":"138518693","full_name":"rudifa/iOS-CustomContainerViewController","owner":"rudifa","description":"An exercice in custom view controller, state machine, passing of data between controllers","archived":false,"fork":false,"pushed_at":"2020-02-21T13:31:12.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-07T15:14:00.360Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rudifa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2018-06-24T22:06:45.000Z","updated_at":"2024-01-19T10:33:53.000Z","dependencies_parsed_at":"2023-04-08T10:38:19.342Z","dependency_job_id":null,"html_url":"https://github.com/rudifa/iOS-CustomContainerViewController","commit_stats":null,"previous_names":["rudifa/ios-customcontainerviewcontroller"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudifa%2FiOS-CustomContainerViewController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudifa%2FiOS-CustomContainerViewController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudifa%2FiOS-CustomContainerViewController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rudifa%2FiOS-CustomContainerViewController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rudifa","download_url":"https://codeload.github.com/rudifa/iOS-CustomContainerViewController/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246725472,"owners_count":20823643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-06T01:40:51.586Z","updated_at":"2025-04-01T23:21:37.433Z","avatar_url":"https://github.com/rudifa.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"#  Experiment with custom Container View Controller\n\n### Code ideas and patterns\n\n**(1)** [Managing View Controllers With Container View Controllers](https://cocoacasts.com/managing-view-controllers-with-container-view-controllers/)\n\nTeaches how to instantiate **custom view controllers** from a storyboard, and how to hook these controllers into a Master container controller.\n\n*A container view controller embeds the content of other view controllers into its own root view.*\n\n**(2)** [Swift: UIStoryboard Protocol](https://medium.com/swift-programming/uistoryboard-safer-with-enums-protocol-extensions-and-generics-7aad3883b44d)\n\nTeaches tricks with enums and generics to simplify the **instantiation of custom view controllers** from storyboards.\n\n**(3)** [Passing Data Between View Controllers in iOS: The Definitive Guide](https://matteomanferdini.com/how-ios-view-controllers-communicate-with-each-other/)\n\nA useful overview.\n\n**(4)** [Why you shouldn’t use delegates in Swift](http://marinbenc.com/why-you-shouldnt-use-delegates-in-swift)\n\nArgues in favor of using callbacks instead of delegate (less coupling, less fuss).\n\n**(5)** [iOS: Three ways to pass data from Model to Controller](https://medium.com/@stasost/ios-three-ways-to-pass-data-from-model-to-controller-b47cc72a4336)\n\nCallbacks, delegation and notification compared.\n\n**(6)** [Swift State Machines, Part 2/3/4](http://www.figure.ink/blog/2015/2/1/swift-state-machines-part-2)\n\nUses ```switch(state, event)```to specify allowed transitions.\n\n### My adaptations\n\nMy function ```instantiateFromStoryboard\u003cT\u003e``` is a simplified version (hardcoded for Main.storyboard) of code shown in **(2)**.\n\n```\nfunc instantiateFromStoryboard\u003cT: UIViewController\u003e() -\u003e T {\n    // load storyboard, instantiate controller and return it\n    let storyboard = UIStoryboard(name: \"Main\", bundle: Bundle.main)\n    let className = String(describing: T.self)\n    guard let viewController = storyboard.instantiateViewController(withIdentifier: className) as? T else {\n        fatalError(\"Could not instantiate a view controller with name: \\(className)\")\n    }\n    return viewController\n}\n```\nExample:\n```\nprivate lazy var redViewController: RedViewController = instantiateFromStoryboard()\n```\n\nIn ```class MasterViewController: UIViewController ``` I add two functions for hooking-in / unhooking child controllers, per **(1)**:\n\n```\n\n    func add(asChildViewController viewController: UIViewController) {\n        // add child\n        addChildViewController(viewController)\n        // add child view as subview and configure it\n        view.addSubview(viewController.view)\n        viewController.view.frame = view.bounds\n        viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n        // notify child view controller\n        viewController.didMove(toParentViewController: self)\n    }\n```\n\n```\n    func remove(asChildViewController viewController: UIViewController) {\n        // notify child\n        viewController.willMove(toParentViewController: nil)\n        // remove child view from superview\n        viewController.view.removeFromSuperview()\n        // notify child view controller\n        viewController.removeFromParentViewController()\n    }\n```\n\nI use a simple state machine in MasterViewController.\n\n```\nenum State {\n    case red, green, blue\n}\n\nenum Event {\n    case cancel, done\n}\n\nclass StateMachine: NSObject {\n    private var state: State = .red\n\n    func nextState(event: Event) -\u003e State {\n        switch (state, event) {\n        case (.red, .done): state = .green\n        case (.green, .done): state = .blue\n        case (.blue, .done): state = .red\n        case (_, .cancel): state = .red\n        }\n        return state\n    }\n\n    var currentState: State {\n        get {\n            return state\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frudifa%2Fios-customcontainerviewcontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frudifa%2Fios-customcontainerviewcontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frudifa%2Fios-customcontainerviewcontroller/lists"}