gpt4 book ai didi

swift - 如果数组是 ObservableObject 的成员,如何绑定(bind)数组和列表?

转载 作者:行者123 更新时间:2023-11-28 10:02:57 26 4
gpt4 key购买 nike

我想创建 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())
}
}

附言如果我用 @State var results: [String] 替换模型,一切正常,但我需要单独的 class MyViewModel: ObservableObject 用于我的目的

最佳答案

修复

更改您的 ForEach阻止

ForEach(model.results, id: \.self) { text in
Text(text)
}

解释

SwiftUI 的错误消息在这里对您没有任何帮助。真正的错误消息(如果将 Text(text) 更改为 Text(text as String) 并删除 $ 之前的 model.results ,您将看到)是“无法推断通用参数‘ID’”。

换句话说,使用ForEach ,您正在迭代的元素需要以两种方式之一进行唯一标识。

  1. 如果元素是结构或类,您可以通过添加属性var id: Hashable 使其符合Identifiable 协议(protocol)。 .你不需要 id本例中的参数。
  2. 另一种选择是专门告诉ForEach使用 id 作为唯一标识符使用什么范围。 更新:由您来保证您的集合没有重复的元素。如果两个元素具有相同的 ID,则对一个 View 所做的任何更改(如偏移量)都会同时影响两个 View 。

在这种情况下,我们选择了选项 2 并告诉 ForEach使用 String 元素本身作为标识符 ( \.self )。我们可以这样做,因为 String 符合 Hashable 协议(protocol)。

$呢? ?

SwiftUI 中的大多数 View 仅获取您应用的状态并根据它布置它们的外观。在此示例中,Text View 仅获取存储在模型中的信息并显示它。但是一些 View 需要能够返回并修改应用程序的状态以响应用户:

  • Toggle 需要更新 Bool 值以响应切换
  • Slider 需要更新 Double 值以响应幻灯片
  • TextField 需要更新 String 值以响应输入

我们确定应用程序状态和 View 之间应该存在这种双向通信的方法是使用 Binding<SomeType> .所以 Toggle 需要你传递给它 Binding<Bool> , slider 需要 Binding<Double> ,而 TextField 需要 Binding<String> .

这是 @State 的位置属性包装器(或 @Published 内部的 @ObservedObject )进来。该属性包装器“包装”它包含在 Binding 中的值。 (以及其他一些保证 SwiftUI 知道在值更改时更新 View 的东西)。如果我们需要获取值,我们可以简单地引用myVariable , 但如果我们需要绑定(bind),我们可以使用简写 $myVariable .

因此,在这种情况下,您的原始代码包含 ForEach($model.results) .换句话说,您是在告诉编译器“迭代这个 Binding<[String]>”,但是 Binding不是您可以迭代的集合。删除 $表示,“遍历此 [String]”,而 Array 是一个您可以遍历的集合。

关于swift - 如果数组是 ObservableObject 的成员,如何绑定(bind)数组和列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58069967/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com