【问题标题】:Binding @Binding / @State to the @Publisher to decouple VM and View Layer将@Binding / @State 绑定到@Publisher 以解耦VM和View Layer
【发布时间】:2021-07-20 01:29:45
【问题描述】:

我想将我的 ViewModel 和 View 层解耦以提高我的 View 的可测试性。 因此,我想将我的属性状态保持在视图内,并且只在需要时对其进行初始化。 但我无法使用@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)

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

【问题讨论】:

  • 绑定它们是什么意思? @Binding 旨在绑定到源自其他 SwiftUI 视图的值,而不是引用类型
  • @SergioBost 我编辑了我的问题,我想完全分离我的视图和 ViewModel 以便我想在我的视图中设计我的视图状态,而不是通过使用观察到的对象,但同时我想要有机会使用 ViewModel 初始化我的视图。

标签: mvvm swiftui observableobject


【解决方案1】:

我已经意识到,通过 Binding(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")
    }

}

【讨论】:

    猜你喜欢
    • 2019-11-14
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多