Как обновить одно дочернее представление в SwiftUI? - PullRequest
1 голос
/ 08 июня 2019

Я пытаюсь установить соединение SwiftUI между дочерним представлением и родительским представлением.Нажав на любое дочернее представление, я хочу перерисовать только тот вид, к которому подключен, а не весь родительский вид.

Текущая реализация, представленная ниже, не позволяет перерисовать вид при щелчке по нему, так каку него есть производное значение.

Я пробовал разные сценарии, добавляя протокол BindableObject к CustomColor, но безуспешно.

class CustomColor: Identifiable {

    let id = UUID()
    var color: Color

    init(color: Color) {
        self.color = color
    }

    func change(to color: Color) {
        self.color = color
    }

}

class ColorStore: BindableObject {

    var colors: [CustomColor] = [] {
        didSet {
            didChange.send(self)
        }
    }

    var didChange = PassthroughSubject<ColorStore, Never>()

    init() {
        self.colors = Array.init(repeating: CustomColor(color: .red), count: 10)
    }

}


struct ContentView: View {

    @EnvironmentObject var colorStore: ColorStore

    var body: some View {
        NavigationView {
            List {
                ForEach(colorStore.colors) { color in
                    ColorShape(color: color)
                }
            }.navigationBarTitle(Text("Colors"))
        }
    }

}

struct ColorShape: View {

    var color: CustomColor

    var body: some View {
        Button(action:
            { self.color.change(to: .blue) }
            , label: {
            ShapeView(shape: Circle(), style: color.color)
        })
    }

}

Вот пользовательский интерфейс, который у меня есть

Ответы [ 2 ]

1 голос
/ 10 июня 2019

Я думаю, что нашел решение.Первая проблема состояла в том, что я инициализировал массив цветов, повторяя один и тот же элемент вместо добавления независимых.

Более того, CustomColor само должно иметь BindableObject соответствие, а не модель (мы не меняеммассив цветов мы меняем каждый цвет).Наконец, нам не нужно оборачивать объекты в элемент ForEach (таким образом мы теряем возможность повторного использования), и вместо этого мы помещаем их в элемент List .

С этимреализации, будет перерисован только вид, который был изменен, а не вся коллекция.

Вот код:

class CustomColor: BindableObject, Identifiable {

    var didChange = PassthroughSubject<CustomColor, Never>()

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

}

0 голосов
/ 08 июня 2019

В настоящее время нет возможности обновить конкретное дочернее представление, и я думаю, что этого нельзя ожидать. Как было сказано в Поток данных через сеанс Swift UI после изменения свойства @State или объекта Bindable - все изменения проходят вниз по иерархии представлений, а среда SwiftUI сравнивает все представления и снова отображает только то, что изменилось. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...