How to detect live changes on TextField in SwiftUI?

后端 未结 5 1751
我在风中等你
我在风中等你 2020-12-05 06:39

I have a simple TextField that binds to the state \'location\' like this,

TextField(\"Search Location\", text: $location)

I want to call a

相关标签:
5条回答
  • 2020-12-05 07:12

    You can create a binding with a custom closure, like this:

    struct ContentView: View {
        @State var location: String = ""
    
        var body: some View {
            let binding = Binding<String>(get: {
                self.location
            }, set: {
                self.location = $0
                // do whatever you want here
            })
    
            return VStack {
                Text("Current location: \(location)")
                TextField("Search Location", text: binding)
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:15

    SwiftUI 1 & 2

    Use onReceive:

    import Combine
    import SwiftUI
    
    struct ContentView: View {
        @State var location: String = ""
    
        var body: some View {
            TextField("Search Location", text: $location)
                .onReceive(Just(location)) { location in
                    // print(location)
                }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:26

    What I found most useful was that TextField has a property that is called onEditingChanged which is called when editing starts and when editing completes.

                   TextField("Enter song title", text: self.$userData.songs[self.songIndex].name, onEditingChanged: { (changed) in
                   if changed {
                       print("text edit has begun")
                   } else {
                       print("committed the change")
                       saveSongs(self.userData.songs)
                   }
    
               }).textFieldStyle(RoundedBorderTextFieldStyle())
                   .font(.largeTitle)
    
    0 讨论(0)
  • 2020-12-05 07:29

    SwiftUI 2.0

    From iOS 14, macOS 11, or any other OS contains SwiftUI 2.0, there is a new modifier called .onChange that detects any change of the given state:

    struct ContentView: View {
        @State var location: String = ""
    
        var body: some View {
            TextField("Your Location", text: $location)
                .onChange(of: location) {
                    print($0) // You can do anything due to the change here.
                    // self.autocomplete($0) // like this
                }
        }
    }
    

    SwiftUI 1.0

    For older iOS and other SwiftUI 1.0 platforms, you can use onReceive:

    .onReceive(location.publisher) { 
        print($0)
    }
    

    Note that it returns the change instead of the entire value. If you need the behavior the same as the onChange, you can use the combine and follow the answer provided by @pawello2222.

    0 讨论(0)
  • 2020-12-05 07:34

    Another solution, if you need to work with a ViewModel, could be:

    import SwiftUI
    import Combine
    
    class ViewModel: ObservableObject {
        @Published var location = "" {
            didSet {
                print("set")
                //do whatever you want
            }
        }
    }
    
    struct ContentView: View {
        @ObservedObject var viewModel = ViewModel()
    
        var body: some View {
            TextField("Search Location", text: $viewModel.location)
        }
    }
    
    0 讨论(0)
提交回复
热议问题