swiftui - View 不会在嵌套 ForEach 循环中重新呈现

标签 swiftui

我有以下组件来呈现半透明字符的网格:

    var body: some View {
        VStack{
            Text("\(self.settings.numRows) x \(self.settings.numColumns)")
            ForEach(0..<self.settings.numRows){ i in
                Spacer()
                    HStack{
                        ForEach(0..<self.settings.numColumns){ j in
                            Spacer()
                            // why do I get an error when I try to multiply i * j
                            self.getSymbol(index:j)
                            Spacer()
                        }
                    }
                Spacer()
            }
        }
    }

settings 是一个环境对象

每当更新settings时,最外层VStack中的文本都会正确更新。但是, View 的其余部分不会更新(网格的尺寸与以前相同)。这是为什么?

第二个问题: 为什么无法访问内部 ForEach 循环中的 i 并将其作为参数传递给函数?

我在外部 ForEach 循环处收到错误:

Generic parameter 'Data' could not be inferred

最佳答案

TL;DR

您的 ForEach 需求 id: \.self添加在您的范围之后。

说明

ForEach 有 several initializers 。您正在使用

init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)

哪里data 必须是一个常数。

如果您的范围可能会发生变化(例如,您正在从数组中添加或删除项目,这将更改上限),那么您需要使用

init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)

您提供 id 的键路径参数,它唯一标识 ForEach 的每个元素循环过去。在 Range<Int> 的情况下,您要循环的元素是 Int指定数组索引,该索引是唯一的。因此您可以简单地使用\.self keypath 让 ForEach 通过它自己的值来识别每个索引元素。

实际情况如下:

struct ContentView: View {
    @State var array = [1, 2, 3]

    var body: some View {
        VStack {
            Button("Add") {
                self.array.append(self.array.last! + 1)
            }

            // this is the key part  v--------v
            ForEach(0..<array.count, id: \.self) { index in
                Text("\(index): \(self.array[index])")
                //Note: If you want more than one views here, you need a VStack or some container, or will throw errors
            }
        }
    }
}

如果你运行它,你会看到当你按下按钮将项目添加到数组时,它们将出现在 VStack 中自动地。如果删除“id: \.self ”,您将看到原始错误:

`ForEach(_:content:)` should only be used for *constant* data. 
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)`
and provide an explicit `id`!"

关于swiftui - View 不会在嵌套 ForEach 循环中重新呈现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58504575/

相关文章:

ios - SwiftUI 不同 View 之间的导航

ios - 将 tapAction 从 SwiftUI 按钮操作发送到 UIView 函数

arrays - 如何仅在搜索栏文本不为空时才运行过滤功能?

ios - SwiftUI 跳转菜单(sectionIndexTitles)

ios - 如何在 SwiftUI 中自动检测 NavigationBarTitle displayMode 变为 .inline 或 .large?

Swift继承函数返回类型不能是子类型

xcode - 停止/隐藏 GTMSessionFetcher 日志 SwiftUI

ios - 从公共(public) API 获取 JSON 以在 SwiftUI 的 ListView 中呈现

swift - 如何在 SwiftUI 中删除列表左侧和右侧的填充

swiftui - 如何正确使用matchedGeometry?