Наблюдайте за изменениями в текстовом поле SwiftUI

Я играю со Swift UI. Я создал табличное представление (список), содержащее все мои желаемые элементы. Также изменение TextField работает при нажатии Enter на клавиатуре. Приятно так быстро построить табличный вид;).

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

Как это можно было сделать в моем коде? Я также прочитал эту документацию здесь https://developer.apple.com/documentation/combine/receiving_and_handling_events_with_combine а>

Я не знаю, как использовать это в своей структуре.

Предлагаемое здесь решение изменения TextField в SwiftUI не работает (больше)

Буду благодарен за каждый намек и каждую идею, которой вы можете со мной поделиться. Часами ищу решение :(.

Мой код выглядит так:

import Foundation
import SwiftUI

struct MyListView: View {
    @ObservedObject var viewModel: MyViewModel

    @State private var query = ""

    var body: some View {

        NavigationView {
            List {
                // how to listen for changes here?
                // if I add onEditingChange here, Get the value only after the user finish search (by pressing enter on the keyboard)
                TextField(String.localizedString(forKey: "search_bar_hint"), text: self.$query) {
                    self.fetchListing()
                } 

                ForEach(viewModel.myArray, id: \.id) { arrayObject in
                    MyRow(arrayObj: arrayObject)
                }
            }
            .navigationBarTitle(navigationBarTitle())
        }
        .onAppear(perform: fetchListing)
    }

    private func fetchListing() {
        query.isEmpty ? viewModel.fetchRequest(for: nil) : viewModel.fetchRequest(for: query)
    }

    private func navigationBarTitle() -> String {
        return query.isEmpty ? String.localizedString(forKey: "my_title") : query
    }
}

person rb90    schedule 25.11.2019    source источник


Ответы (2)


Простой пользовательский binding - хорошее начало для этой задачи:

struct ContentView: View {
    @State private var query = ""

    var body: some View {

        let binding = Binding<String>(
            get: { self.query },
            set: { self.query = $0; self.textFieldChanged($0) }
        )

        return NavigationView {
            List {
                TextField("Text", text: binding)
            }
        }
    }

    private func textFieldChanged(_ text: String) { print(text) }
}

Протестировано и работает

person Mojtaba Hosseini    schedule 25.11.2019
comment
Великий Моджтаба, большое спасибо за этот ответ. Это именно то, что я искал. И работает отлично. Ты спас мне день :). - person rb90; 26.11.2019

Вот так

struct ContentView: View {
    @State private var email = ""
    var body: some View {
        TextField("Email", text: $email)
            .onChange(of: email) { text in
                print(text)
            }
    }
}
person Zeeshan    schedule 26.07.2020
comment
Я получаю следующую ошибку Value of type 'TextField<Text>' has no member 'onChange' - person Learn2Code; 12.10.2020
comment
Решение также доступно в iOS 14 или новее. - person C. Skjerdal; 30.11.2020