Swiftui 视图不会在嵌套的ForEach循环中重新渲染

Swiftui 视图不会在嵌套的ForEach循环中重新渲染,swiftui,Swiftui,我使用以下组件渲染半透明字符网格: var主体:一些视图{ VStack{ 文本(\(self.settings.numRows)x\(self.settings.numColumns)) ForEach(0..ForEach应仅用于常量数据。因此,它仅根据定义计算一次。请尝试将其包装到列表中,您将看到错误记录如下: ForEach,Int,TupleView>,Spacer)>>count(7)!=其初始计数(0)。ForEach(u:content:)应仅用于常量数据。相反,应将数据与可识别

我使用以下组件渲染半透明字符网格:

var主体:一些视图{
VStack{
文本(\(self.settings.numRows)x\(self.settings.numColumns))

ForEach(0..ForEach应仅用于常量数据。因此,它仅根据定义计算一次。请尝试将其包装到列表中,您将看到错误记录如下:

ForEach,Int,TupleView>,Spacer)>>count(7)!=其初始计数(0)。
ForEach(u:content:)
应仅用于常量数据。相反,应将数据与
可识别的
一致,或使用
ForEach(u:id:content:)
并提供明确的
id

我也对此感到惊讶,并且找不到任何关于这一限制的官方文件

至于为什么不可能访问内部ForEach循环中的i,我认为您可能有一个误导性的编译器错误,与代码片段中缺少的其他内容有关。它在用最佳猜测(Xcode 11.1,Mac OS 10.14.4)完成缺少的部分后为我编译

以下是我提出的让您的ForEach检查一些可识别的内容:



struct SettingsElement: Identifiable {
    var id: Int { value }

    let value: Int

    init(_ i: Int) { value = i }
}

class Settings: ObservableObject {
    @Published var rows = [SettingsElement(0),SettingsElement(1),SettingsElement(2)]
    @Published var columns = [SettingsElement(0),SettingsElement(1),SettingsElement(2)]
}

struct ContentView: View {
    @EnvironmentObject var settings: Settings

    func getSymbol(index: Int) -> Text { Text("\(index)") }

    var body: some View {
        VStack{
            Text("\(self.settings.rows.count) x \(self.settings.columns.count)")
            ForEach(self.settings.rows) { i in
                VStack {
                    HStack {
                        ForEach(self.settings.columns) { j in
                            Text("\(i.value) \(j.value)")
                        }
                    }
                }
            }
        }
    }
}

太长,读不下去了 您的ForEach需要在您的范围后添加
id:\.self

解释 ForEach有。您正在使用

init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)
您为
id
参数提供一个键路径,该参数唯一地标识
ForEach
循环的每个元素。对于
范围
,循环的元素是一个指定数组索引的
Int
,该数组索引是唯一的。因此,您只需使用
\.self
键路径即可获得For每个索引元素都通过自己的值标识每个索引元素

以下是实际情况:

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
            }
        }
    }
}

使用John M.的技术来构造可识别的东西会导致一个比我期望的更简洁和优雅的解决方案。这样构造一个可识别的解决方案是个好主意。我在解决方案中做了很多工作(我更新了我的答案).@Asadefa如果没有错误的上下文,我无法判断您遇到了什么问题。我建议您使用不起作用的代码问一个新问题。一般来说,您将闭包作为参数传递,闭包需要返回一些内容(可能是
视图
),但您没有返回任何内容(空元组
()
表示闭包返回
Void
)。我试图输入两个文本,但它抛出了一个错误。我建议编辑如果ForEach循环在选择器中,则需要额外一点魔法,将.id(self.array)添加到选择器中(将“array”更新为数组的名称),如下回答:非常感谢
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
            }
        }
    }
}
`ForEach(_:content:)` should only be used for *constant* data. 
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)`
and provide an explicit `id`!"