Действие, когда пользователь нажимает кнопку удаления на клавиатуре в SwiftUI - PullRequest
0 голосов
/ 08 ноября 2019

Я пытаюсь запустить функцию, когда пользователь нажимает кнопку удаления на клавиатуре, когда он пытается изменить текстовое поле.

Как я могу это сделать?

enter image description here

1 Ответ

1 голос
/ 08 ноября 2019

Да, это возможно, однако для этого необходимо создать подкласс UITextField и создать свой собственный UIViewRepresentable

Этот ответ основан на фантастической работе, проделанной Костантино Пистанья в его статье среднего но нам нужно проделать немного больше работы.

Во-первых, нам нужно создать наш подкласс UITextField, это также должно соответствовать протоколу UITextFieldDelegate.

class WrappableTextField: UITextField, UITextFieldDelegate {
    var textFieldChangedHandler: ((String)->Void)?
    var onCommitHandler: (()->Void)?
    var deleteHandler: (() -> Void)?

    override func deleteBackward() {
        super.deleteBackward()
        deleteHandler?()
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if let nextField = textField.superview?.superview?.viewWithTag(textField.tag + 1) as? UITextField {
            nextField.becomeFirstResponder()
        } else {
            textField.resignFirstResponder()
        }
        return false
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if let currentValue = textField.text as NSString? {
            let proposedValue = currentValue.replacingCharacters(in: range, with: string)
            textFieldChangedHandler?(proposedValue as String)
        }
        return true
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        onCommitHandler?()
    }
}

Поскольку мы создаем собственную реализацию TextField, нам нужны три функции, которые мы можем использовать для обратных вызовов.

  1. textFieldChangeHandler это будет вызвано при обновлении свойства текста и позволит нам изменить значение состояния, связанное с нашим Textfield.
  2. onCommitHandler, которое будет вызвано, когдамы закончили редактирование нашего TextField
  3. deleteHandler, которое будет вызываться при выполнении действия по удалению.

Приведенный выше код показывает, как они используются. Часть, которая вас особенно интересует, - это override func deleteBackward(), переопределив это, мы можем подключиться при нажатии кнопки удаления и выполнить над ней действие. В зависимости от вашего варианта использования, вы можете захотеть, чтобы deleteHandler вызывался до того, как вы вызовете super.

Далее нам нужно создать UIViewRepresentable.

struct MyTextField: UIViewRepresentable {
    private let tmpView = WrappableTextField()

    //var exposed to SwiftUI object init
    var tag:Int = 0
    var placeholder:String?
    var changeHandler:((String)->Void)?
    var onCommitHandler:(()->Void)?
    var deleteHandler: (()->Void)?

    func makeUIView(context: UIViewRepresentableContext<MyTextField>) -> WrappableTextField {
        tmpView.tag = tag
        tmpView.delegate = tmpView
        tmpView.placeholder = placeholder
        tmpView.onCommitHandler = onCommitHandler
        tmpView.textFieldChangedHandler = changeHandler
        tmpView.deleteHandler = deleteHandler
        return tmpView
    }

    func updateUIView(_ uiView: WrappableTextField, context: UIViewRepresentableContext<MyTextField>) {
        uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
        uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
    }
}

ThisЗдесь мы создаем нашу версию SwiftUI нашего WrappableTextField. Мы создаем наш WrappableTextField и его свойства. В функции makeUIView мы присваиваем эти свойства. Наконец, в updateUIView мы устанавливаем свойства обхвата контента, но вы можете не делать этого, это действительно зависит от вашего варианта использования.

Наконец, мы можем создать небольшой рабочий пример.

struct ContentView: View {

    @State var text = ""

    var body: some View {
        MyTextField(tag: 0, placeholder: "Enter your name here", changeHandler: { text in
            // update the state's value of text
            self.text = text
        }, onCommitHandler: {
            // do something when the editing finishes
            print("Editing ended")
        }, deleteHandler: {
            // do something here when you press delete
            print("Delete pressed")
        })
    }
}
...