Last active
November 20, 2023 06:04
-
-
Save WinterArch/8087f3487b69080f1bc35eff4c94c7a7 to your computer and use it in GitHub Desktop.
Model-View Design Patterns Plus
This file contains hidden or 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
| import SwiftUI | |
| /// ContentView: Model | |
| struct ContentView { | |
| /// viewmodel first, one View one View Model, intuitively. if need. | |
| @StateObject private var viewmodel = ViewModel() | |
| /// properties here | |
| let recordTime: Date | |
| /// states here | |
| @State private var counter: Int = 0 | |
| } | |
| /// ContentView: View | |
| extension ContentView: Equatable, View { | |
| static func == (lhs: ContentView, rhs: ContentView) -> Bool { | |
| lhs.counter == rhs.counter | |
| } | |
| var body: some View { | |
| VStack { | |
| Text("counter\(counter)") | |
| Text("drag this: \(viewmodel.lastestAt.x), \(viewmodel.lastestAt.y)") | |
| .padding(30) | |
| .gesture( | |
| DragGesture() | |
| .onChanged { value in | |
| viewmodel.lastestAt = value.location | |
| } | |
| ) | |
| .background { | |
| // FREQUENT updates | |
| Color.init( | |
| red: .random(in: 0...1), | |
| green: .random(in: 0...1), | |
| blue: .random(in: 0...1) | |
| ) | |
| } | |
| } | |
| } | |
| } | |
| /// ContentView: ViewModel | |
| extension ContentView { | |
| class ViewModel: ObservableObject { | |
| @Published var lastestAt = CGPoint() | |
| } | |
| } | |
| #Preview { | |
| ContentView(recordTime: Date()) | |
| .equatable() | |
| } |
This file contains hidden or 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
| import SwiftUI | |
| struct StateView { // 祖先视图 | |
| @State private var box = Box() | |
| struct Box { | |
| var times: Int = 0 | |
| var record: Date = .now | |
| let pub = PublishBox() | |
| } | |
| } | |
| extension StateView.Box { | |
| class PublishBox: ObservableObject { | |
| @Published var color: Color = .clear | |
| } | |
| } | |
| fileprivate extension StateView { | |
| struct EnvironmentBox: EnvironmentKey { | |
| static var defaultValue: Box = .init() | |
| } | |
| } | |
| fileprivate extension EnvironmentValues { | |
| var environmentBox: StateView.Box { | |
| get { self[StateView.EnvironmentBox.self] } | |
| set { self[StateView.EnvironmentBox.self] = newValue } | |
| } | |
| } | |
| extension StateView: View { | |
| var body: some View { | |
| VStack { | |
| Text("click:\(box.times)") | |
| .onTapGesture { | |
| box.times += 1 | |
| box.pub.color = .random | |
| } | |
| Text("record:\(box.record)") | |
| .onTapGesture { | |
| box.record = .now | |
| box.pub.color = .white | |
| } | |
| SubView(box: box) | |
| .equatable() | |
| SubView2(box: $box) | |
| } | |
| .environment(\.environmentBox, box) | |
| } | |
| struct SubView: View, Equatable { | |
| static func == (lhs: StateView.SubView, rhs: StateView.SubView) -> Bool { | |
| lhs.box.times == rhs.box.times | |
| } | |
| let box: StateView.Box | |
| var body: some View { | |
| VStack { | |
| Text("click:\(box.times)") | |
| .onTapGesture { | |
| // box.times += 1 | |
| // print("\(box.record)") | |
| } | |
| .background { | |
| Color.random | |
| } | |
| Text("SubViewrecord:\(box.record)") | |
| .background { | |
| Color.random | |
| } | |
| StateView.SubView3() | |
| } | |
| } | |
| } | |
| struct SubView2: View { | |
| @Binding var box: StateView.Box | |
| var body: some View { | |
| VStack { | |
| Text("click:\(box.times)") | |
| .onTapGesture { | |
| box.times += 1 | |
| // print("\(box.record)") | |
| } | |
| .background { | |
| Color.random | |
| } | |
| StateView.SubView(box: box) | |
| .equatable() | |
| .background { | |
| Color.random | |
| } | |
| } | |
| } | |
| } | |
| struct SubView3: View { | |
| /// 环境注入-数据跨级传递 | |
| @Environment(\.environmentBox) var box: StateView.Box | |
| /// 状态 - 接收器变量 | |
| @State private var receivedColor: Color = .clear | |
| var body: some View { | |
| VStack { | |
| Text("hello,\(box.times)") | |
| Text("world!\(receivedColor.description)") | |
| .onReceive(box.pub.$color) { | |
| receivedColor = $0 | |
| } | |
| .background { | |
| receivedColor | |
| } | |
| } | |
| } | |
| } | |
| } | |
| fileprivate extension Color { | |
| static var random: Color { | |
| .init( | |
| red: .random(in: 0...1), | |
| green: .random(in: 0...1), | |
| blue: .random(in: 0...1) | |
| ) | |
| } | |
| } | |
| #Preview { | |
| StateView() | |
| } | |
| struct VMStyleView { | |
| @StateObject private var vm = ViewModel() | |
| class ViewModel: ObservableObject { | |
| @Published var times: Int = 0 | |
| @Published var record: Date = .now | |
| } | |
| } | |
| extension VMStyleView: View { | |
| var body: some View { | |
| VStack { | |
| Text("click:\(vm.times)") | |
| .onTapGesture { | |
| vm.times += 1 | |
| // print("\(box.record)") | |
| } | |
| Text("record:\(vm.record)") | |
| .onTapGesture { | |
| vm.record = .now | |
| } | |
| SubView(vm: vm) | |
| .equatable() | |
| SubView2(vm: vm) | |
| } | |
| } | |
| struct SubView: View, Equatable { | |
| static func == (lhs: VMStyleView.SubView, rhs: VMStyleView.SubView) -> Bool { | |
| lhs.vm.times == rhs.vm.times | |
| } | |
| @ObservedObject var vm: VMStyleView.ViewModel | |
| var body: some View { | |
| VStack { | |
| Text("click:\(vm.times)") | |
| .onTapGesture { | |
| vm.times += 1 | |
| // print("\(box.record)") | |
| } | |
| .background { | |
| Color.random | |
| } | |
| Text("record:\(vm.record)") | |
| .onTapGesture { | |
| vm.record = .now | |
| } | |
| .background { | |
| Color.random | |
| } | |
| } | |
| } | |
| } | |
| struct SubView2: View { | |
| @ObservedObject var vm: VMStyleView.ViewModel | |
| var body: some View { | |
| VStack { | |
| Text("click:\(vm.times)") | |
| .onTapGesture { | |
| vm.times += 1 | |
| // print("\(box.record)") | |
| } | |
| VMStyleView.SubView(vm: vm) | |
| .equatable() | |
| } | |
| .background { | |
| Color.random | |
| } | |
| } | |
| } | |
| } | |
| #Preview { | |
| VMStyleView() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment