Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Respond to specific key press in UITextField (UIViewRepresentable)

I would like to respond to keyboard presses in a UITextField wrapped as UIViewRepresentable. This is the code for the wrapper view:

import SwiftUI
import UIKit

struct ContentView: View {
    @State var text: String = "Hello."
    
    var body: some View {
        WrappedUITextField(text: $text)
    }
}

struct WrappedUITextField: UIViewRepresentable {
    @Binding var text: String
    
    func makeCoordinator() -> Coordinator {
        Coordinator($text)
    }
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.delegate = context.coordinator
        textField.text = text
        textField.autocapitalizationType = .none
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        if text != context.coordinator.currentText { uiView.text = text }
    }
}

class Coordinator: NSObject, UITextFieldDelegate {
    
    var text: Binding<String>
    var currentText: String
    
    init(_ text: Binding<String>) {
        self.text = text
        currentText = text.wrappedValue
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
        guard let oldText = textField.text,
              let textRange = Range(range, in: oldText) else {
            return false
        }
        
        self.currentText = oldText.replacingCharacters(in: textRange, with: string)
        print("oldText = \"\(oldText)\", new text = \"\(currentText)\"")
        
        self.text.wrappedValue = currentText
        return true
    }
    
    func textFieldDidChangeSelection(_ textField: UITextField) {
        print("textFieldDidChangeSelection")
    }
}

Specifically, I want to trigger some action when pressing left/right arrow key when the cursor is at the left/rightmost edge, e.g., "|abc", where "|" is the cursor position, and the user presses left arrow.

None of the UITextFieldDelegate methods will work here because pressing left/right arrow key when the cursor is already on the left/rightmost edge (respectively) neither changes the text contents (e.g., textFieldDidBeginEditing() won’t be called) nor cursor position (e.g., textFieldDidChangeSelection() won’t be called).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

How do I respond to left/right arrow keys in this case? Something like a pressesBegan() method would be nice here, but I couldn’t figure out how to integrate that with UIViewRepresentable (e.g., adding override func pressesBegan(...) to Coordinator doesn’t work).

Thanks

>Solution :

Just create your class inherited UITextField and override handler there

func makeUIView(context: Context) -> UITextField {
    let textField = MyTextField()                   // << here !!
    textField.delegate = context.coordinator
    textField.text = text
    textField.autocapitalizationType = .none
    return textField
}

class MyTextField: UITextField {
   override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
       // handle here requried events

       // call super if not handled above
       super.pressesBegan(presses, with: event)
   }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading