Den*_*hin 2 swift swiftui combine swiftui-list
我想创建MyViewModel
它从网络获取数据然后更新结果数组。MyView
应该订阅$model.results
并显示List
填充结果。
不幸的是,我收到一个关于“没有更多上下文的表达式类型不明确”的错误。
如何正确使用ForEach
这种情况?
import SwiftUI
import Combine
class MyViewModel: ObservableObject {
@Published var results: [String] = []
init() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.results = ["Hello", "World", "!!!"]
}
}
}
struct MyView: View {
@ObservedObject var model: MyViewModel
var body: some View {
VStack {
List {
ForEach($model.results) { text in
Text(text)
// ^--- Type of expression is ambiguous without more context
}
}
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView(model: MyViewModel())
}
}
Run Code Online (Sandbox Code Playgroud)
PS如果我用@State var results: [String]
一切正常的方式替换模型,但我需要单独class MyViewModel: ObservableObject
用于我的目的
修复
将您的ForEach
块更改为
ForEach(model.results, id: \.self) { text in
Text(text)
}
Run Code Online (Sandbox Code Playgroud)
解释
SwiftUI 的错误消息在这里对您没有任何帮助。真正的错误消息(你会看到,如果你改变Text(text)
到Text(text as String)
并删除$
之前model.results
),是“通用参数‘ID’不能推断”。
换句话说,要使用ForEach
,您正在迭代的元素需要以两种方式之一进行唯一标识。
var id: Hashable
。id
在这种情况下,您不需要该参数。ForEach
使用id
参数明确说明将什么用作唯一标识符。更新:由您来保证您的集合没有重复的元素。如果两个元素具有相同的 ID,则对一个视图所做的任何更改(如偏移量)都会发生在两个视图上。在这种情况下,我们选择了选项 2 并被告知ForEach
使用 String 元素本身作为标识符 ( \.self
)。我们可以这样做,因为 String 符合 Hashable 协议。
怎么样的$
?
SwiftUI 中的大多数视图只获取应用程序的状态并根据它来布置它们的外观。在这个例子中,Text 视图只是获取存储在模型中的信息并显示它。但是有些视图需要能够返回并修改应用程序的状态以响应用户:
我们确定应用程序状态和视图之间应该存在这种双向通信的方式是使用Binding<SomeType>
. 所以一个 Toggle 需要你传递 a Binding<Bool>
,一个 Slider 需要一个Binding<Double>
,而一个 TextField 需要一个Binding<String>
.
这就是@State
属性包装器(或@Published
在 内部@ObservedObject
)的Binding
用武之地。该属性包装器将它包含的值“包装”在 a 中(以及其他一些东西,以保证 SwiftUI 知道在值更改时更新视图)。如果我们需要获取值,我们可以简单地引用myVariable
,但是如果我们需要绑定,我们可以使用简写$myVariable
。
因此,在这种情况下,您的原始代码包含ForEach($model.results)
. 换句话说,您告诉编译器“迭代这个Binding<[String]>
”,但Binding
不是您可以迭代的集合。去掉$
“迭代这个 [String]”,Array是一个可以迭代的集合。
归档时间: |
|
查看次数: |
1790 次 |
最近记录: |