简体   繁体   中英

SwiftUI TextField onChange not triggered

New to SwiftUI and trying to figure something out. I'm implementing a barcode scanner, which consists of a TextField , Button and CameraView . CameraView will scan a barcode, display the serial number in the TextField , and the Button will use the serial number to pair a bluetooth device.

So now in my SwiftUI class, I have my UI setup like so:

struct BTLEConnectionView: View {
    @ObservedObject var bluetoothConnectorViewModel: BluetoothConnectorViewModel
    @ObservedObject var barcodeScannerViewModel = BarcodeScannerViewModel()
    @Binding var deviceID: String

    @State private var serialNumber: String = ""

    var body: some View {
        VStack {
           HStack {
               DeviceIDTextField(deviceID: $deviceID, serialNumber: $serialNumber, viewModel: barcodeScannerViewModel)
            
               PairButton(bluetoothConnectorViewModel: bluetoothConnectorViewModel, barcodeScannerViewModel: barcodeScannerViewModel, serialNumber: $serialNumber)
           }
           .padding()
    
           BarcodeScannerView(barscannerViewModel: barcodeScannerViewModel)
       }
   }
}

struct DeviceIDTextField: View {
   @Binding var deviceID: String
   @Binding var serialNumber: String
   @ObservedObject var viewModel: BarcodeScannerViewModel

   var body: some View {
       let serialNumberBinding = Binding<String>(
           get: { viewModel.barcodeString.isEmpty ? serialNumber : viewModel.barcodeString },
           set: { serialNumber = viewModel.barcodeString.isEmpty ? $0 : viewModel.barcodeString }
       )
    
       TextField(NSLocalizedString("textfield.hint.device.id", comment: ""), text: serialNumberBinding)
           .textFieldStyle(RoundedBorderTextFieldStyle())
           .onChange(of: serialNumber, perform: { value in
               serialNumber = value
           })
   }

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

struct PairButton: View {
   @ObservedObject var bluetoothConnectorViewModel: BluetoothConnectorViewModel
   @ObservedObject var barcodeScannerViewModel: BarcodeScannerViewModel
   @Binding var serialNumber: String

   var body: some View {
       Button(action: {
           withAnimation {
               bluetoothConnectorViewModel.connectBluetoothLowEnergyDevice(deviceID: serialNumber)
           }
       }) {
           ButtonText(text: NSLocalizedString("button.text.pair", comment: ""))
       }
   }
}

So basically I want to make it so: If user scans barcode, the serial is added to the textfield, press pair button to use that serial and call the method and pass in the serial number. If user deletes the prepopulated serial, enters their own, it should update the textfield, and pressing the button should use the new serial number.

Right now when I scan a barcode, it populates the text field, however the onChange callback isn't picked up until I actually type in the TextField, so the result is never set for the method call.

Any help with this would be great, hope it makes sense.

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)
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM