繁体   English   中英

在 SwiftUI PreviewProvider 中更改 model 视图 state

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM