SwiftMVCR is an sample iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)
-
Clone this repository.
git clone git@github.com:yokurin/Swift-MVCR-iOS.git -
Open
SwiftMVCR.xcodeprojin Xcode. -
Run
MVCR means Model, View, Controller, Router.
You can easy to know transitions of app. But, Not testable Architecture
Model must implement Modelable.
protocol Modelable { // nop }Example
final class Model: Modelable { ... }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 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 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) } }WIP ...
WIP ...
- Xcode 10.0+
- Swift 4.2+
git clone git@github.com:yokurin/Swift-MVCR-iOS.git Tsubasa Hayashi, yoku.rin.99@gmail.com
SwiftMVCR is available under the MIT license. See the LICENSE file for more info.


