[英]Change model view state in SwiftUI PreviewProvider
我正在努力寻找一种干净的方法来预览具有视图 model 的 SwiftUI 视图和一些 state 可以在视图的整个生命周期中改变的视图。 这是一些稍微做作的代码来说明我使用的模式。
import SwiftUI
enum NetworkState {
case idle
case loading
case hasData
case error
}
public class MyViewModel: ObservableObject {
@Published var results: [String] = []
@Published var state: NetworkState = NetworkState.idle
func load() {
self.results = ["One", "Two", "Three"]
self.state = .hasData
}
}
public struct MyView: View {
//MARK: View Model
@ObservedObject var viewModel: MyViewModel
//MARK: Body
public var body: some View {
switch self.viewModel.state {
case NetworkState.idle:
Text("Tap to load").onTapGesture {
self.viewModel.load()
}
case NetworkState.loading:
Text("Loading ...")
case NetworkState.hasData:
ScrollView {
ForEach(self.viewModel.results, id: \.self) { string in
Text(string)
}
}
case NetworkState.error:
Text("There was an error")
}
}
//MARK: Init
public init(viewModel model: MyViewModel) {
self.viewModel = model
}
}
现在,我无法预览和更改.state
变量来查看我的视图在其整个生命周期中的不同排列。 这是我的两次不成功的尝试。
//Does not compile
struct MyView_Previews: PreviewProvider {
static var previews: some View {
let viewModel = MyViewModel()
viewModel.state = .error
MyView(viewModel: viewModel)
}
}
//Can not manipulate state after initalization. Also does not compile.
struct MyViewTwo_Previews: PreviewProvider {
static let viewModel = MyViewModel()
static var previews: some View {
viewModel.state = .error
MyView(viewModel: viewModel)
}
}
他们都因这个错误而失败
Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
我确信有一种方法,我希望它尽可能干净。
您的预览中缺少return
声明。 如果您没有return
,编译器会假定它是ViewBuilder
并将顶层视为隐式返回,但您正在分配变量等工作。
struct MyView_Previews: PreviewProvider {
static var previews: some View {
let viewModel = MyViewModel()
viewModel.state = .idle
return MyView(viewModel: viewModel)
}
}
struct MyViewTwo_Previews: PreviewProvider {
static let viewModel = MyViewModel()
static var previews: some View {
viewModel.state = .idle
return MyView(viewModel: viewModel)
}
}
更新,在一个预览中显示多个视图:
struct MyView_Previews: PreviewProvider {
static var previews: some View {
let viewModel = MyViewModel()
viewModel.state = .idle
let viewModel2 = MyViewModel()
viewModel2.state = .hasData
let viewModel3 = MyViewModel()
viewModel3.state = .error
return Group {
MyView(viewModel: viewModel)
MyView(viewModel: viewModel2)
MyView(viewModel: viewModel3)
}
}
通过带有默认 arguments 的构造函数使用依赖注入,例如
public class MyViewModel: ObservableObject {
@Published var results: [String]
@Published var state: NetworkState
init(results: [String] = [], state: NetworkState = .idle) {
self.results = results
self.state = state
}
func load() {
self.results = ["One", "Two", "Three"]
self.state = .hasData
}
}
那么您可以将其用作
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView(viewModel: MyViewModel(state: .error))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.