SwiftUI TextField внутри ListView становится пустым после фильтрации элементов списка - PullRequest
0 голосов
/ 30 октября 2019

Я работаю над приложением для iOS, которое отображает список элементов, которые можно редактировать. Для этого я использую List и TextField для каждого из этих элементов.

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

Вот очень простойВоспроизведение:

import SwiftUI

let allItems = ["1. Foo", "1. Bar", "1. Baz", "2. Goo", "2. Gar", "2. Gaz"]

struct ContentView: View {
    @State private var items = [String]()
    @State private var filterPrefix = "1"

    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) { item in
                    RowView(item: item)
                }
            }
            .navigationBarItems(trailing: Button("Toggle") {
                self.filterPrefix = (self.filterPrefix == "1" ? "2" : "1")
                self.items = allItems.filter { $0.starts(with: self.filterPrefix) }
            })
            .navigationBarTitle("Items", displayMode: .inline)
        }
        .onAppear {
            self.items = allItems.filter { $0.starts(with: self.filterPrefix) }
        }
    }
}

struct RowView: View {
    var item: String

    @State private var inputText = ""

    var body: some View {
        VStack {
            TextField("", text: $inputText)
        }
        .onAppear {
            print("Item: \(self.item)") // This prints the item successfully
            self.inputText = self.item
        }
    }
}

После нескольких нажатий Toggle, TextField в итоге оказывается пустым. Однако код в onAppear по-прежнему печатает текстовое значение штрафа.

Вот рисунок:

Example


AmЯ что то не так делаю? Должен ли я добавить TextField только после нажатия? (кажется, не очень хорошая идея, но я в недоумении, почему это не работает)

Я работаю на Xcode 11.2 beta 2 (11B44), но та же проблема возникает на 11.1 и обаiOS 13.1 и 13.2


РЕДАКТИРОВАТЬ: чтобы еще больше усложнить ситуацию, я изменил строку, чтобы включить текст и текстовое поле:

        HStack {
            Text(item)
            TextField("", text: $inputText)
        }

И теперь значение TextField непусто, если это не последний элемент в списке. Мне начинает пахнуть жуком

1 Ответ

0 голосов
/ 30 октября 2019

Просто отфильтруйте массив элементов на месте:

struct FilterView: View {

    @State private var items = ["1. Foo", "1. Bar", "1. Baz",
                                "2. Goo", "2. Gar", "2. Gaz"]
    @State private var filterPrefix = "1"

    var body: some View {
        NavigationView {
            List {
                ForEach(items.filter({ $0.starts(with: self.filterPrefix) }), id: \.self) { item in
                    RowView(item: item)
                }
            }
            .navigationBarItems(trailing: Button("Toggle") {
                self.filterPrefix = (self.filterPrefix == "1" ? "2" : "1")
            })
            .navigationBarTitle("Items", displayMode: .inline)
        }
    }
}
...