【问题标题】:Displaying activity indicator while loading async request in SwiftUI在 SwiftUI 中加载异步请求时显示活动指示器
【发布时间】:2020-03-16 08:19:36
【问题描述】:

我有一个显示从 API 获取数据的列表的基本视图。我想在从 API 检索数据时实现一个活动指示器。在 MVC 中,我们可以使用委托和协议,并使视图控制器继承协议,在模型完成获取数据后,我们调用委托来告诉视图控制器数据已完成检索(现在隐藏活动指示器等.)。如何在 SwiftUI 和它的 MVVM 风格中实现类似的东西?

我已经尝试从这个问题中实现一个活动指示器,我只是不知道如何以及何时停止它:Activity indicator in SwiftUI

My SourcesViewModel(它从 newsapi.org 获取新闻文章来源)

import UIKit

class SourcesViewModel: Identifiable {

    let id = UUID()

    let source: Sources

    init(source: Sources) {
        self.source = source
    }

    var name: String {
        return self.source.sourceName
    }

    var description: String {
        return self.source.sourceDescription
    }
}

我的 SourcesListViewModel:

import Combine

class SourcesListViewModel: ObservableObject {

    init() {
        fetchSources()
    }

    @Published var sources = [SourcesViewModel]()
    private func fetchSources() {
        NetworkManager.shared.getSourceData { (sources) in
            self.sources = sources.map(SourcesViewModel.init)
        }
    }
}

最后,我的 SourcesView:

import SwiftUI

struct SourcesView: View {
    @ObservedObject var model = SourcesListViewModel()

    var body: some View {
        ActivityIndicatorView(isShowing: .constant(true)) {
            NavigationView {
                List(self.model.sources) { source in
                    VStack(alignment: .center) {
                        Text(source.name)

                        Text(source.description)
                            .foregroundColor(.secondary)
                            .lineLimit(3)
                    }
                    .navigationBarTitle(Text("Sources"), displayMode: .inline)
                }
            }
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        SourcesView()
    }
}

结果:

【问题讨论】:

    标签: ios swift cocoa swiftui


    【解决方案1】:

    您的视图模型应该具有加载状态,如下所示

    @Published var loading = false
    private func fetchSources() {
        self.loading = true
        NetworkManager.shared.getSourceData { (sources) in
            self.sources = sources.map(SourcesViewModel.init)
            self.loading = false
        }
    }
    

    和活动指示器应该绑定到它,像

    ActivityIndicatorView(isShowing: $model.loading) {
    

    【讨论】:

    • 谢谢!只是错过了@pratap answer中的 .constant
    • 如果是绑定的,没看到ActivityIndi​​catorView是什么,那最好直接$model.loading
    【解决方案2】:
    import Combine
    
    class SourcesListViewModel: ObservableObject {
        @Published var loading = true
        @Published var sources = [SourcesViewModel]()
    
        init() {
            fetchSources()
        }
    
    
        private func fetchSources() {
            NetworkManager.shared.getSourceData { (sources) in
                self.sources = sources.map(SourcesViewModel.init)
                self.loading=false
            }
        }
    }
    
    
    
    import SwiftUI
    
    struct SourcesView: View {
        @ObservedObject var model = SourcesListViewModel()
    
        var body: some View {
            ActivityIndicatorView(isShowing: .constant(self.model.loading)) {
                NavigationView {
                    List(self.model.sources) { source in
                        VStack(alignment: .center) {
                            Text(source.name)
    
                            Text(source.description)
                                .foregroundColor(.secondary)
                                .lineLimit(3)
                        }
                        .navigationBarTitle(Text("Sources"), displayMode: .inline)
                    }
                }
            }
        }
    }
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            SourcesView()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多