在SwiftUI中加载异步请求时显示活动指示器

时间:2019-11-20 14:58:50

标签: ios swift cocoa swiftui

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

我尝试通过此问题实施活动指标,只是不知道如何以及何时停止:Activity indicator in SwiftUI

我的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()
    }
}

结果:

how to stop loading

2 个答案:

答案 0 :(得分: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) {

答案 1 :(得分:1)

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()
    }
}