基于 VIewModel 状态更新 SwiftUI 视图?

时间:2021-03-13 11:30:40

标签: swift swiftui combine

我在我的 SwiftUI 视图中使用 @State 进行了设置,并在视图中执行所有操作(加载 API 等),但是在尝试对其进行重构时,不使用 @ViewBuilder@State使用 @ObservedObject ViewModel,我失去了根据 @State 变量动态更改视图的能力

我的代码现在是

    
    @ObservedObject private var contentViewModel: ContentViewModel
    
    init(viewModel: ContentViewModel) {
        self.contentViewModel = viewModel
    }
    
    var body: some View {
        if contentViewModel.isLoading {
            loadingView
        }
        else if contentViewModel.fetchError != nil {
            errorView
        }
        else if contentViewModel.movies.isEmpty {
            emptyListView
        } else {
            moviesList
        }
    }

但是,每当这些 viewmodel 属性发生变化时,视图就不会像我在类中将它们用作 @State 属性时那样更新...

ViewModel 如下:

final class ContentViewModel: ObservableObject {

    var movies: [Movie] = []
    var isLoading: Bool = false
    var fetchError: String?
    
    private let dataLoader: DataLoaderProtocol
    
    init(dataLoader: DataLoaderProtocol = DataLoader()) {
        self.dataLoader = dataLoader

        fetch()
    }

    func fetch() {
        isLoading = true
        dataLoader.loadMovies { [weak self] result, error in
            guard let self = `self` else { return }
            self.isLoading = false
            guard let result = result else {
                return print("api error fetching")
            }
            guard let error = result.errorMessage, error != "" else {
                return self.movies = result.items
            }
            return self.fetchError = error
        }
    }

现在我如何将这 3 个状态决定属性绑定到视图结果,现在它们已被抽象到视图模型?

谢谢

1 个答案:

答案 0 :(得分:3)

将@Published 放在所有 3 个属性之前,如下所示:

 @Published var movies: [Movie] = []
 @Published var isLoading: Bool = false
 @Published var fetchError: String?

通过使类符合 ObservableObject 但它本身什么都不做,您几乎就到了那里。然后,您需要确保使用上面显示的 @Published 自动发送更新或手动发送 objectWillChange.send()

编辑:

另外你应该知道,如果你把这些数据传递给任何孩子,你应该让父母的属性为 @StateObject,孩子的为 ObservedObject