我有一个基本视图,该视图显示一个列表,该列表从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()
}
}
结果:
答案 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()
}
}