How to update a single child view in SwiftUI?

前端 未结 3 384
一向
一向 2021-02-06 17:01

I am trying to establish a SwiftUI connection between the child view and the parent view. By clicking on any child view, I want to redraw only the view that has been tapped, not

3条回答
  •  日久生厌
    2021-02-06 17:49

    I think I've found a solution. The first problem was that I initialized array of colors by repeating the same element instead of adding independent ones.

    What is more CustomColor itself should have BindableObject conformance, not the model (we don't change the array of colors, we change each color). Lastly, we don't need to wrap objects in ForEach element (we loose reusability that way), and instead we put them in List element.

    With this implementation, only the view that has been changed will be redrawn, not the entire collection.

    Here is the code:

    class CustomColor: BindableObject, Identifiable {
    
        var didChange = PassthroughSubject()
    
        let id = UUID()
        var color: Color {
            didSet {
                self.didChange.send(self)
            }
        }
    
        init(color: Color) {
            self.color = color
        }
    
        func change(toColor color: Color) {
            self.color = color
        }
    
    }
    
    class ColorStore {
    
        var colors: [CustomColor] = []
    
        init() {
            (0...10).forEach { _ in colors.append(CustomColor(color: .red)) }
        }
    
    }
    
    
    struct ContentView: View {
    
        let colorStore: ColorStore
    
        var body: some View {
            NavigationView {
                List(colorStore.colors) { color in
                    ColorShape(color: color)
                }.navigationBarTitle(Text("Colors"))
            }
        }
    
    }
    
    struct ColorShape: View {
    
        @ObjectBinding var color: CustomColor
    
        var body: some View {
            Button(action: { self.color.change(toColor: .blue) }, label: {
                ShapeView(shape: Circle(), style: color.color)
            })
        }
    
    }
    
    

提交回复
热议问题