Skip to content

SwiftMVCR is an example iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)

License

Notifications You must be signed in to change notification settings

yokurin/Swift-MVCR-iOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SwiftMVCR (Model, View, Controller, Router)

SwiftMVCR is an sample iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)

Language

Sample App

Architecture

Run Sample

  1. Clone this repository.

    git clone [email protected]:yokurin/Swift-MVCR-iOS.git
    
  2. Open SwiftMVCR.xcodeproj in Xcode.

  3. Run

Description

MVCR means Model, View, Controller, Router.
You can easy to know transitions of app. But, Not testable Architecture

Model

Model must implement Modelable.

protocol Modelable {
    // nop
}

Example

final class Model: Modelable {
    ...
}

View (including UIViewController)

View must implement Viewable. Viewable has Default Extension.
※ View is not just View like UIView etc in this case.

protocol Viewable: AnyObject {
    func push(_ vc: UIViewController, animated: Bool)
    func present(_ vc: UIViewController, animated: Bool)
    func pop(animated: Bool)
    func dismiss(animated: Bool)
    func dismiss(animated: Bool, completion: @escaping (() -> Void))
}

extension Viewable where Self: UIViewController {

    func push(_ vc: UIViewController, animated: Bool) {
        self.navigationController?.pushViewController(vc, animated: animated)
    }

    func present(_ vc: UIViewController, animated: Bool) {
        self.present(vc, animated: animated, completion: nil)
    }

    func pop(animated: Bool) {
        self.navigationController?.popViewController(animated: animated)
    }

    func dismiss(animated: Bool) {
        self.dismiss(animated: animated, completion: nil)
    }

    func dismiss(animated: Bool, completion: @escaping (() -> Void)) {
        self.dismiss(animated: animated, completion: completion)
    }
}

Example

extension ViewController: Viewable {}

Controller (including UIViewController)

Controller must implement Controllerable.

protocol Controllerable {
    associatedtype M: Modelable
    associatedtype R: Routerable
    var model: M! { get }
    var router: R! { get }
}

Example

final class ViewController: UIViewController, Controllerable {
    
    ...
    
    static func configure(entryModel: EntryModel) -> ViewController {
        let controller = ViewController()
        controller.router = RouterOutput(controller)
        controller.model = Model(entryModel: entryModel)
        return controller
    }
    
    private(set) var model: Model!
    private(set) var router: RouterOutput!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    ...
}

UIViewController has roles that View and Controller. But, its ok.

Router

Router must implement Routerable.

protocol Routerable {
    var view: Viewable! { get }

    func dismiss(animated: Bool)
    func dismiss(animated: Bool, completion: @escaping (() -> Void))
    func pop(animated: Bool)
}

extension Routerable {
    func dismiss(animated: Bool) {
        view.dismiss(animated: animated)
    }

    func dismiss(animated: Bool, completion: @escaping (() -> Void)) {
        view.dismiss(animated: animated, _completion: completion)
    }

    func pop(animated: Bool) {
        view.pop(animated: animated)
    }
}

Example

struct EntryModel {}

final class RouterInput {
    func push(from: Viewable, entryModel: EntryModel) {
        let controller = ViewController.configure(entryModel: entryModel)
        from.push(controller, animated: true)
    }

    func present(from: Viewable, entryModel: EntryModel) {
        let controller = ViewController.configure(entryModel: entryModel)
        from.present(controller, animated: true)
    }
}

final class RouterOutput: Routerable {

    weak private(set) var view: Viewable!

    init(_ view: Viewable) {
        self.view = view
    }

    func transitionToOther(entryModel: EntryModel) {
        OtherRouterInput().push(from: view, entryModel: entryModel)
    }
}

Unit Test

WIP ...

xctemplate

WIP ...

Requirements

  • Xcode 10.0+
  • Swift 4.2+

Installation

git clone [email protected]:yokurin/Swift-MVCR-iOS.git

Author

Tsubasa Hayashi, [email protected]

License

SwiftMVCR is available under the MIT license. See the LICENSE file for more info.

About

SwiftMVCR is an example iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages