SwiftUI 4: представление назначения navigationDestination() не обновляется при изменении состояния

Во время экспериментов с новымв SwiftUI 4 я обнаружил, что при изменении состояния возвращаемое целевое представление не обновляется. См. код ниже.

      struct ContentView: View {
    @State var data: [Int: String] = [
        1: "One",
        2: "Two",
        3: "Three",
        4: "Four"
    ]

    var body: some View {
        NavigationStack {
            List {
                ForEach(Array(data.keys).sorted(), id: \.self) { key in
                    NavigationLink("\(key)", value: key)
                }
            }
            .navigationDestination(for: Int.self) { key in
                if let value = data[key] {
                    VStack {
                        Text("This is \(value)").padding()
                        Button("Modify It") {
                            data[key] = "X"
                        }
                    }
                }
            }
        }
    }
}

Действия по воспроизведению проблемы:

  1. Запустите код и нажмите на первый элемент в списке. Это приведет вас к подробному представлению об этом элементе.

  2. Подробный вид показывает стоимость элемента. Он также имеет кнопку для изменения значения. Нажмите на эту кнопку. Вы заметите, что значение в подробном представлении не меняется.

Я отладил проблему, установив точки останова в другом месте. Мои наблюдения:

  • Когда я нажал кнопку, код вбыть казненным. Это как и ожидалось.

  • Но переданное замыкание не выполняется, что объясняет, почему подробное представление не обновляется.

Кто-нибудь знает, это ошибка или ожидаемое поведение? Если это не ошибка, как я могу запрограммировать обновление значения в подробном представлении?

Кстати, если я вернусь к корневому представлению и нажму на первый элемент, чтобы снова перейти к его подробному представлению, закрытие перейдет квыполниться, и в подробном представлении измененное значение будет отображаться правильно.

1 ответ

The buttonправильно меняет значение. По умолчаниюnavigationDestinationне создаетBindingотношение между родителем и дочерним элементом, создающим переданные значенияimmutable.

Поэтому вам следует создать отдельныйstructребенку для достиженияBindableповедение:

      struct ContentView: View {
    @State var data: [Int: String] = [
        1: "One",
        2: "Two",
        3: "Three",
        4: "Four"
    ]

    var body: some View {
        NavigationStack {
            List {
                ForEach(Array(data.keys).sorted(), id: \.self) { key in
                    NavigationLink("\(key)", value: key)
                }
            }
            .navigationDestination(for: Int.self) { key in
                SubContentView(key: key, data: $data)
            }
        }
    }
}

struct SubContentView: View {
    let key: Int
    @Binding var data: [Int: String]
    var body: some View {
        if let value = data[key] {
            VStack {
                Text("This is \(value)").padding()
                Button("Modify It") {
                    data[key] = "X"
                }
            }
        }
    }
}
Другие вопросы по тегам