View is not rerendered in Nested ForEach loop

前端 未结 2 1302
孤独总比滥情好
孤独总比滥情好 2020-12-18 20:28

I have the following component that renders a grid of semi transparent characters:

    var body: some View {
               


        
2条回答
  •  猫巷女王i
    2020-12-18 20:55

    ForEach should only be used for constant data. So it is only evaluated once by definition. Try wrapping it in a List and you will see errors being logged like:

    ForEach, Int, TupleView<(Spacer, HStack, Int, TupleView<(Spacer, Text, Spacer)>>>, Spacer)>> count (7) != its initial count (0). ForEach(_:content:) should only be used for constant data. Instead conform data to Identifiable or use ForEach(_:id:content:) and provide an explicit id!

    I was surprised by this as well, and unable to find any official documentation about this limitation.

    As for why it is not possible for you to access the i in the inner ForEach-loop, I think you probably have a misleading compiler error on your hands, related to something else in the code that is missing in your snippets. It did compile for me after completing the missing parts with a best guess (Xcode 11.1, Mac OS 10.14.4).

    Here is what I came up with to make your ForEach go over something Identifiable:

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

提交回复
热议问题