0

Currently my iOS custom keyboard has a delete all button. Here is its code when clicked:

func deletekeyPressed(sender: UIButton!) {

    for _ in 1..<10000 {
        (textDocumentProxy as UIKeyInput).deleteBackward()
    }

}

The problem is, whenever I click the button there is a noticeable pause before all the text is deleted. I am pretty sure this is because I am calling deleteBackward() 10000 times.

Is there a faster way to delete all the text?

shim
  • 9,289
  • 12
  • 69
  • 108
Foobar
  • 7,458
  • 16
  • 81
  • 161
  • Can't you just set the `UITextView`/`UITextField`'s `text` attribute to an empty string? – NRitH Jun 22 '16 at 15:32
  • Also, this question has nothing whatsoever to do with custom keyboards. It's only about `UIDocument`s and `UITextView`s. – NRitH Jun 22 '16 at 15:33
  • 2
    It has everything to do with custom keyboards. I am making an app extensions that is an app that installs a custom keyboard for the user which the user can use wherever they want. As such, I cannot access the UITextfield object because a custom keyboard had a limited amount of ways to interact with the text – Foobar Jun 22 '16 at 16:26
  • Then you should have explained that you don't have access to the text field. – NRitH Jun 22 '16 at 17:49
  • 1
    I already explained that I was making a IOS custom keyboard which implies that you cannot access the text field. – Foobar Jun 22 '16 at 19:58

1 Answers1

0

If you call deleteBackwards 10000 times, this means that 10000 deleteBackwards commands have to be serialized into some representation that can be transmitted via XPC, sent over to the host process, deserialized, and then applied. This could be the source of your delay.

I would batch your deleteBackwards calls into chunks that delete no more than the current document context you have available, then wait for the next textDidChange call, and if it is within X milliseconds of the last one, delete some more with the new context, as you can be fairly sure that the user didn't tap another text field so soon after pressing your button.

Below is some pseudocode that demonstrates what I mean.

var lastDeleteAllPressed: Double
let threshHold = 0.1 // you'll need to test on a real device to get a real value for this.
func textDidChange() {
  //whatever else you need to do
  if CACurrentMediaTime - lastDeleteAllPressed < threshHold && !proxy.isEmpty {
    deleteKeyPressed() 
  }
}
func deleteKeyPressed() {

    let length = proxy.contextBeforeInput.append(proxy.contextAfterInput).length
    0...length.forEach { deleteBackwards() }
    lastDeleteAllPressed = CACurrentMediaTime()
}

This approach has the benefit of not doing unnecessary work, and of working even if there are more than 10000 characters in the document the user is editing. The drawback is that it could fail if the host process takes unnaturally long to send back a textDidChange event.

Ben Pious
  • 4,765
  • 2
  • 22
  • 34