How to refresh ForEach to display number of elements after array size change (SwiftUI, Xcode 11 Beta 5)

I'm trying to implement a View that can change the number of displayed items (created by a ForEach loop) when the size of the content array changes, just like a shopping app might change its number of available items after the user pulls down to refresh

Here's some code I've tried so far. If I recall correctly, these are for Xcode beta 4, but not beta 5:

  • If the size of the array increases, the loop will still display the original number of elements
  • Decreasing size of array causes index out of bounds error

code:

import SwiftUI

struct test : View {
    @State var array:[String] = []
    @State var label = "not pressed"
    var body: some View {
        VStack{
            Text(label).onTapGesture {
                self.array.append("ForEach refreshed")
                self.label = "pressed"
            }
            ForEach(0..<array.count){number in
                Text(self.array[number])
            }
        }
}
}

#if DEBUG
struct test_Previews: PreviewProvider {
    static var previews: some View {
        test()
    }
}
#endif

I'm new to SwiftUI and GUI programming in general, and it feels like everything is defined at startup and it's hard to change it afterwards (eg: reset the View after the user navigates away and back). Thanks a lot for the loop issue Solution or any tips to make View more dynamic!

Best answer

The Beta 5 release notes say:

The retroactive conformance of Int to the Identifiable protocol is removed. Change any code that relies on this conformance to pass .self to the id parameter of the relevant initializer. Constant ranges of Int continue to be accepted:

List(0..<5) {
   Text("Rooms")
}

However, you shouldn’t pass a range that changes at runtime. If you use a variable that changes at runtime to define the range, the list displays views according to the initial range and ignores any subsequent updates to the range.

You should change  ForEach to receive an array, not a range. Ideally  Identifiable an array to avoid using  \.self. But depending on your goal, this still works:

import SwiftUI

struct ContentView : View {
    @State var array:[String] = []
    @State var label = "not pressed"
    var body: some View {
        VStack{
            Text(label).onTapGesture {
                self.array.append("ForEach refreshed")
                self.label = "pressed"
            }
            ForEach(array, id: \.self) { item in
                Text(item)
            }
        }
    }
}

Or as suggested by rob mayoff , if you need an index:

struct ContentView : View {
    @State var array:[String] = []
    @State var label = "not pressed"
    var body: some View {
        VStack{
            Text(label).onTapGesture {
                self.array.append("ForEach refreshed")
                self.label = "pressed"
            }
            ForEach(array.indices, id: \.self) { index in
                Text(self.array[index])
            }
        }
    }
}

Regarding swift - How to refresh number of ForEach's displaying elements after array's size changes (SwiftUI, Xcode 11 Beta 5), ​​we found a similar question on Stack Overflow: swift - How to refresh number of ForEach's displaying elements after array's size changes  ( SwiftUI, Xcode 11 Beta 5) - Stack Overflow

おすすめ

転載: blog.csdn.net/weixin_42610770/article/details/132053728