Created
August 10, 2022 20:19
-
-
Save ivanornes/571a0cc5958b78fd18cc46eaf251e568 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ContentView2.swift | |
// MVVM | |
// | |
// Created by Ivan Ornes on 10/8/22. | |
// | |
import SwiftUI | |
class Model: ObservableObject { // Rich domain | |
@Published var counter: Int = 0 | |
func increment() { | |
counter += 1 | |
} | |
} | |
// <GrandChildView: View> Avoids requiring AnyView | |
struct ChildView<GrandChildView: View>: View { | |
private let vm: ChildViewModel | |
private let grandChildView: GrandChildView | |
init(vm: ChildViewModel, grandChildView: GrandChildView) { | |
self.vm = vm | |
self.grandChildView = grandChildView | |
} | |
var body: some View { | |
VStack { | |
grandChildView | |
} | |
} | |
} | |
class GrandChildViewModel: ObservableObject { | |
private let model: Model | |
init(model: Model) { | |
self.model = model | |
} | |
func increment() { | |
model.increment() | |
} | |
} | |
struct GrandChildView: View { | |
private let vm: GrandChildViewModel | |
init(vm: GrandChildViewModel) { | |
self.vm = vm | |
} | |
var body: some View { | |
VStack { | |
Button("Increment from GrandChildView") { | |
vm.increment() | |
} | |
} | |
} | |
} | |
class ContentViewModel: ObservableObject { | |
private let model: Model | |
@Published var counter: String = "0" | |
init(model: Model) { | |
self.model = model | |
_ = model.$counter.sink { | |
// Adapt domain model to what the UI should show | |
self.counter = "\($0)" | |
} | |
} | |
func increment() { | |
model.increment() | |
} | |
} | |
class ChildViewModel: ObservableObject { | |
private let model: Model | |
init(model: Model) { | |
self.model = model | |
} | |
} | |
struct ContentView<ChildView: View>: View { | |
let vm: ContentViewModel | |
let childView: ChildView | |
var body: some View { | |
VStack { | |
// Follow the Demeter law, do not go too deep in the dependency dependencies | |
// Uses the formatted counter of the view model | |
Text(vm.counter) | |
.font(.largeTitle) | |
Button("Increment from ContentView") { | |
vm.increment() | |
} | |
childView | |
} | |
} | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
let model = Model() | |
let grandChildView = GrandChildView(vm: GrandChildViewModel(model: model)) | |
let childView = ChildView(vm: ChildViewModel(model: model), grandChildView: grandChildView) | |
ContentView(vm: ContentViewModel(model: model), childView: childView) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MVVMApp.swift | |
// MVVM | |
// | |
// Created by Ivan Ornes on 10/8/22. | |
// | |
import SwiftUI | |
@main | |
struct MVVMApp: App { | |
@StateObject private var model = Model() | |
var body: some Scene { | |
WindowGroup { // App composition | |
let grandChildView = GrandChildView(vm: GrandChildViewModel(model: model)) | |
let childView = ChildView(vm: ChildViewModel(model: model), grandChildView: grandChildView) | |
ContentView(vm: ContentViewModel(model: model), childView: childView) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment