SwiftMVCR is an example iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)
SwiftMVCR is an sample iOS App written in Swift using the MVCR architecture. (Model, View, Controller, Router)
Clone this repository.
git clone [email protected]:yokurin/Swift-MVCR-iOS.git
Open SwiftMVCR.xcodeproj
in 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 …
git clone [email protected]:yokurin/Swift-MVCR-iOS.git
Tsubasa Hayashi, [email protected]
SwiftMVCR is available under the MIT license. See the LICENSE file for more info.