【发布时间】:2021-04-30 17:50:46
【问题描述】:
我已经准备好a simple test project at Github 来演示我的问题:
我有一个 SwiftUI 列表,我尝试在其中显示 var items:[String]。
当我只有一个像下面这样的硬编码数组时 - 它可以正常工作并在 iPhone 中显示:
items = (1...200).map { number in "Item \(number)" }
但是当我尝试获取 JSON 网页并将结果附加到 items 时,我得到了错误:
转义闭包捕获变异的“自我”参数
我知道items.append(str) 行从 dataTask 闭包中修改了父 ContentView 对象,这出于某种原因并不好......但是如何修复我的代码呢?
import SwiftUI
struct TopResponse: Codable {
let data: [Top]
}
struct Top: Codable {
let uid: Int
let elo: Int
let given: String
let photo: String?
let motto: String?
let avg_score: Double?
let avg_time: String?
}
struct ContentView: View {
var items:[String];
init() {
items = (1...200).map { number in "Item \(number)" }
let url = URL(string: "https://slova.de/ws/top")!
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
let decoder = JSONDecoder()
guard let data = data else { return }
do {
let tops = try decoder.decode(TopResponse.self, from: data)
for (index, top) in tops.data.enumerated() {
let str = "\(index + 1): \(top.given)"
items.append(str) // this results in compile error!
}
} catch {
print("Error while parsing: \(error)")
}
}
task.resume()
}
var body: some View {
List(items, id: \.self) { item in
Text(item)
}
}
}
我应该将items 移出视图吗?
我的最终目标是在 Core Data 中包含 JSON 数据,然后从中更新/通知列表。
我在 Android 中有一个这样的应用程序(结构为 MVVM),现在我正在尝试将它移植到 SwiftUI,作为一个 Swift 新手。
更新:
我已按照 achu 的建议添加了 a view model file(谢谢!),它确实有效,但只有当我拖动列表时,列表才会更新为新项目。并且有一个警告
[SwiftUI] 不允许从后台线程发布更改;确保在模型更新时从主线程发布值(通过接收(on:) 等运算符)。
【问题讨论】:
-
修改数组时实际上是在修改结构体,但结构体是一个值对象,因此您可以这样做。您应该有一个管理数据的类,并且在您的视图结构中没有该代码。
-
这个 SO question + answer 将有助于理解问题。
-
不要滥用 SwiftUI 视图作为 控制器。在额外的
ObservableObject类和publish中加载数据 -
这是我在 SwiftUI 中如何做到这一点的教程:youtube.com/watch?v=h42OHc5CRBQ .. 虽然我建议学习使用组合方法:youtube.com/watch?v=fdxFp5vU6MQ&t=0s。这是 MVVM 上的另一个内容,可帮助您找到更好的方向 youtube.com/watch?v=wEf1YS4vyW8