#swiftui
#swiftui
Вопрос:
Как передать @Binding
в ViewModel.
Давайте рассмотрим простой пример,
struct TopView: View {
@State var isPresented: Bool
var body: some View {
SubView(isPresented: $isPresented)
}
}
struct SubView: View {
@Binding var isPresented: Bool
}
Затем, если мы хотим использовать шаблон MVVM,
Безопасно ли использовать @Binding
в ObservableObject
?
Например, безопасно ли писать,
struct TopView: View {
@State var isPresented: Bool
var body: some View {
SubView(model: SubViewModel(isPresented: $isPresented))
}
}
struct SubView: View {
@ObservedObject var model: SubViewModel
}
// In "SubViewModel.swift"
import Foundation
import Combine
import SwiftUI
public final class SubViewModel: ObservedObject {
@Binding var isPresented: Bool
public init(isPresented: Binding<Bool>) {
self._isPresented = isPresented
}
}
Как бы вы это сделали? Аналогично, в том числе как передать environmentObject в модель представления?
Ответ №1:
Вы описываете основное использование ObservableObject
. @Binding
и @State
используются только в View
Учебные пособия Apple SwiftUI могут быть очень полезны, чтобы вы понимали концепции SwiftUI. https://developer.apple.com/tutorials/swiftui /
В вашем коде есть несколько основных ошибок, об изменениях в коде я упомянул ниже.
import SwiftUI
struct PassingBinding: View {
var body: some View {
TopView1()//Best Practice
//TopView2()//Singleton Pattern
}
}
///This is the best way to do it
///https://developer.apple.com/tutorials/swiftui/handling-user-input
struct TopView1: View {
@StateObject var model: SubViewModel = SubViewModel()
var body: some View {
VStack{
SubView1().environmentObject(model)
Button(action: {
self.model.isPresented.toggle()
}, label: {
Text("Toggle isPresented")
})
}
}
}
struct SubView1: View {
@EnvironmentObject var model: SubViewModel
var body: some View {
Text("SubView - isPresented == (model.isPresented.description)")
}
}
///Another way that has some specifc uses is to use a Singleton model
///https://developer.apple.com/documentation/swift/cocoa_design_patterns/managing_a_shared_resource_using_a_singleton
struct TopView2: View {
@StateObject var model: SubViewModel = SubViewModel.shared
var body: some View {
VStack{
SubView2()
Button(action: {
self.model.isPresented.toggle()
}, label: {
Text("Toggle isPresented")
})
} }
}
struct SubView2: View {
@StateObject var model: SubViewModel = SubViewModel.shared
var body: some View {
Text("SubView - isPresented == (model.isPresented.description)")
}
}
///This item can be Observed "ObservableObject" vs I am Observing this object "ObservedObject"
///https://developer.apple.com/documentation/combine/observableobject
public final class SubViewModel: ObservableObject {
static let shared: SubViewModel = SubViewModel()//Singleton Pattern
@Published var isPresented: Bool = false //Initialize here this is the source for the View
//@Binding and @State is are only used in View struct not in an ObservableObject.https://developer.apple.com/documentation/swiftui/binding
}
struct PassingBinding_Previews: PreviewProvider {
static var previews: some View {
PassingBinding()
}
}