Issue #776

We need to use a custom Binding to trigger onChange as onEditingChanged is only called when the user selects the textField, and onCommit is only called when return or done button on keyboard is tapped.

import UIKit
import SwiftUI
import EasySwiftUI

struct SearchBar: View {
    @Binding
    var searchText: String
    let onChange: () -> Void
    @State
    private var showsCancelButton: Bool = false

    var body: some View {
        return HStack {
            textField
            cancelButton
        }
    }

    private var searchTextBinding: Binding<String> {
        Binding<String>(get: {
            searchText
        }, set: { newValue in
            DispatchQueue.main.async {
                searchText = newValue
                onChange()
            }
        })
    }

    private var textField: some View {
        HStack {
            Image(systemName: SFSymbol.magnifyingglass.rawValue)

            TextField("Search", text: searchTextBinding, onEditingChanged: { isEditing in
                withAnimation {
                    self.showsCancelButton = true
                }
                onChange()
            }, onCommit: {
                // No op
            })
            .foregroundColor(.primary)

            Button(action: {
                self.searchText = ""
            }) {
                Image(systemName: SFSymbol.xmarkCircleFill.rawValue)
                    .opacity(searchText == "" ? 0 : 1)
            }
        }
        .padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6))
        .foregroundColor(.secondary)
        .background(Color(.systemBackground))
        .cornerRadius(10.0)
    }

    @ViewBuilder
    private var cancelButton: some View {
        if showsCancelButton  {
            Button("Cancel") {
                UIApplication.shared.endEditing(true)
                withAnimation {
                    self.searchText = ""
                    self.showsCancelButton = false
                }
                onChange()
            }
            .foregroundColor(Color(.systemBlue))
        }
    }
}

extension UIApplication {
    func endEditing(_ force: Bool) {
        self.windows
            .filter{$0.isKeyWindow}
            .first?
            .endEditing(force)
    }
}