我有一个AsyncContentView
在视图出现时处理数据加载并处理加载视图和内容的切换(取自此处swiftbysundell):
struct AsyncContentView<P:Parsable, Source:Loader<P>, Content: View>: View {
@ObservedObject private var source: Source
private var content: (P.ReturnType) -> Content
init?(source: Source, reloadAfter reloadTime:UInt64 = 0, @ViewBuilder content: @escaping (P.ReturnType) -> Content) {
self.source = source
self.content = content
}
func loadInfo() {
Task {
await source.loadData()
}
}
var body: some View {
switch source.state {
case .idle:
return AnyView(Color.clear.onAppear(perform: loadInfo))
case .loading:
return AnyView(ProgressView("Loading..."))
case .loaded(let output):
return AnyView(content(output))
}
}
}
为了完整起见,这是Parsable
协议:
protocol Parsable: ObservableObject {
associatedtype ReturnType
init()
var result: ReturnType { get }
}
LoadingState
和_Loader
enum LoadingState<Value> {
case idle
case loading
case loaded(Value)
}
@MainActor
class Loader<P:Parsable>: ObservableObject {
@Published public var state: LoadingState<P.ReturnType> = .idle
func loadData() async {
self.state = .loading
await Task.sleep(2_000_000_000)
self.state = .loaded(P().result)
}
}
这是我正在使用的一些虚拟数据:
struct Interface: Hashable {
let name:String
}
struct Interfaces {
let interfaces: [Interface] = [
Interface(name: "test1"),
Interface(name: "test2"),
Interface(name: "test3")
]
var selectedInterface: Interface { interfaces.randomElement()! }
}
现在我把它们放在一起,这样就可以了。它处理async
显示加载视图 2 秒的函数,然后使用提供的数据生成内容视图:
struct ContentView: View {
class SomeParsableData: Parsable {
typealias ReturnType = Interfaces
required init() { }
var result = Interfaces()
}
@StateObject var pageLoader: Loader<SomeParsableData> = Loader()
@State private var selectedInterface: Interface?
var body: some View {
AsyncContentView(source: pageLoader) { result in
Picker(selection: $selectedInterface, label: Text("Selected radio")) {
ForEach(result.interfaces, id: \.self) {
Text($0.name)
}
}
.pickerStyle(.segmented)
}
}
}
现在我遇到的问题是,这个数据包含应该选择哪个段。在我的真实应用程序中,这是一个获取数据的 Web 请求,其中包括选择了哪个段。
那么我怎样才能让这个视图更新selectedInterface
@state
属性呢?
如果我只是添加该行
self.selectedInterface = result.selectedInterface
进入我的AsyncContentView
我得到这个错误
类型 '()' 不能符合 'View'