Mvvm 将@Binding/@状态绑定到@Publisher以解耦VM和视图层

Mvvm 将@Binding/@状态绑定到@Publisher以解耦VM和视图层,mvvm,swiftui,observableobject,Mvvm,Swiftui,Observableobject,我想解耦ViewModel和视图层,以提高视图的可测试性。 因此,我希望在视图中保留我的属性状态,并且只在需要时初始化它们。 但是我不能用@Published属性初始化@Binding或@States。有没有办法在init函数中耦合它们 我只是将下面的示例代码添加到 而不是 import SwiftUI class ViewModel: ObservableObject { @Published var str: String = "a" @Publishe

我想解耦ViewModel和视图层,以提高视图的可测试性。 因此,我希望在视图中保留我的属性状态,并且只在需要时初始化它们。 但是我不能用@Published属性初始化@Binding或@States。有没有办法在init函数中耦合它们

我只是将下面的示例代码添加到

而不是

import SwiftUI

class ViewModel: ObservableObject {
    @Published var str: String = "a"
    @Published var int: Int = 1 { didSet { print("ViewModel int = \(int)")} }
    
    init() {
        print("ViewModel initialized")
    }
}

struct ContentView: View {
    
    @ObservedObject vM = ViewModel()
    
    var body: some View {
        Button(action: { vM.int += 1; print(int) }, label: {
        Text("Button")
        })
    }
}
我希望在视图中不使用@ObservedObject来实现这一点

import SwiftUI

class ViewModel: ObservableObject {
    @Published var str: String = "a"
    @Published var int: Int = 1 { didSet { print("ViewModel int = \(int)")} }
    
    init() {
        print("ViewModel initialized")
    }
}

struct ContentView: View {
    
    @Binding var str: String
    @Binding var int: Int
    
    var body: some View {
        Button(action: { int += 1; print(int) }, label: {
        Text("Button")
        })
    }
}

extension ContentView {
    
        init(viewModel:ObservedObject<ViewModel> = ObservedObject(wrappedValue: ViewModel())) {
        // str: Binding<String> and viewModel.str: Published<String>.publisher 
        // type so that I cannot bind my bindings to viewModel. I must accomplish
        // this by using @ObservedObject but this time my view couples with ViewModel
        _str = viewModel.wrappedValue.$str 
        _int = viewModel.wrappedValue.$int
        print("ViewCreated")
    }
    
}



// Testing Init
ContentView(str: Binding<String>, int: Binding<Int>)

// ViewModel Init
ContentView(viewModel: ViewModel)
导入快捷界面
类ViewModel:ObservableObject{
@已发布的var str:String=“a”
@已发布的变量int:int=1{didSet{print(“ViewModel int=\(int)”)}
init(){
打印(“ViewModel已初始化”)
}
}
结构ContentView:View{
@绑定变量str:String
@绑定变量int:int
var body:一些观点{
按钮(操作:{int+=1;打印(int)},标签:{
文本(“按钮”)
})
}
}
扩展内容视图{
init(viewModel:ObservedObject=ObservedObject(wrappedValue:viewModel()){
//str:Binding和viewModel.str:Published.publisher
//键入,这样我就无法将绑定绑定到viewModel。我必须完成
//这是通过使用@ObservedObject实现的,但这次我的视图与ViewModel耦合
_str=viewModel.wrappedValue.$str
_int=viewModel.wrappedValue.$int
打印(“创建视图”)
}
}
//测试初始化
ContentView(str:Binding,int:Binding)
//视图模型初始化
ContentView(视图模型:视图模型)

这样我就无法将它们彼此绑定,我只想将我的绑定或状态属性绑定到已发布的属性。

我意识到通过绑定(get:{},set{}),我可以实现这一点。如果任何人想要分离他们的ViewModel和View图层,他们可以使用以下方法:

import SwiftUI

class ViewModel: ObservableObject {
    @Published var str: String = "a"
    @Published var int: Int = 1 { didSet { print("ViewModel int = \(int)")} }

    init() {
        print("ViewModel initialized")
    }
}

struct ContentView: View {

    @Binding var str: String
    @Binding var int: Int

    var body: some View {
        Button(action: { int += 1; print(int) }, label: {
            Text("Button")
        })
    }
}

extension ContentView {

    init(viewModel:ViewModel = ViewModel()) {
        _str = Binding ( get: { viewModel.str }, set: { viewModel.str = $0 } )
        _int = Binding ( get: { viewModel.int }, set: { viewModel.int = $0 } )

        print("ViewCreated")
    }

}

你是什么意思
@Binding
是指绑定到源自其他SwiftUI视图的值,而不是引用types@SergioBost我编辑我的问题,我想完全分离我的视图和ViewModel,这样我想在视图中设计我的视图状态,而不是使用观察对象,但同时我想有机会使用ViewModel初始化我的视图。