何时使用 @State 与 @Published

Sto*_*oic 8 mvvm swift swiftui

我觉得这是一个已经在某个地方被问过的问题,但我找不到太多相关内容。

当使用变量来更新 UI 时,我们何时/为什么要@State在视图中使用而不是使用@Published在 ViewModel 中使用?

这是我试图掌握 MVVM 架构的背景。我总体上理解这种差异,只是当涉及到两者都可以轻松以相同方式完成的事情时。

下面,我有 2 个示例执行相同的操作,但其中一个使用ViewModel,而@State另一个则使用@PublishedViewModel。一种方法是否比另一种更好(用于更新 UI 目的?)

@State例子:

struct MyView: View {
    @State var backgroundIsRed = false

    var body: some View {
        ZStack {
            if backgroundIsRed {
                Color.red
            } else {
                Color.green
            }
        }
        .onTapGesture { backgroundIsRed.toggle() }

    }
}
Run Code Online (Sandbox Code Playgroud)

@Published例子:

class ViewModel: ObservableObject {
    @Published var backgroundIsRed = false
}

struct MyView: View {

    @StateObject var viewModel = ViewModel()

    var body: some View {
        ZStack {
            if viewModel.backgroundIsRed {
                Color.red
            } else {
                Color.green
            }
        }
        .onTapGesture { viewModel.backgroundIsRed.toggle() }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 4

例如,我想说“已发布”方法可以帮助您为虚拟机创建测试结构。

以您的示例为例,您可以创建一个协议:

protocol ViewModelProtocol {
   var backgroundIsRed: Bool { get }
   var date: Date { get } // Created for example purposes
}
Run Code Online (Sandbox Code Playgroud)

进而:

class ViewModel: ViewModelProtocol, ObservableObject {
    @Published var backgroundIsRed = false
    @Published var date = Date()
}

class ViewModelMock: ViewModelProtocol, ObservableObject {
    @Published var backgroundIsRed = true
    @Published var date = Mock.Date
}

struct MyView: View {
    @StateObject var viewModel: ViewModelProtocol = ViewModel()
    //@StateObject var viewModel: ViewModelProtocol = ViewModelMock()

    var body: some View {
        ZStack {
            if viewModel.backgroundIsRed {
                Color.red
            } else {
                Color.green
            }
        }
        .onTapGesture { viewModel.backgroundIsRed.toggle() }
    }
}
Run Code Online (Sandbox Code Playgroud)

另一方面,状态方法提供了一种更直接的方式来实现逻辑。

除此之外,没有任何特别的理由认为其中一个比另一个更好。希望这可以帮助您选择在每种情况下应该使用哪一个。