Why shouldChangeTextInRange be called multiple times using predictive input?

Predictive input iOS8 calls the following delegate method of UITextView several times, as a result of which the selected word is inserted several times into the view.

This code works to enter single letters and copy / paste, but not when using the predictive input panel; why not?

 - (BOOL) textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text { textView.text = [textView.text stringByReplacingCharactersInRange:range withString:text]; return false; } 

Using this code; if I enter an empty UITextView and tap "The" in the predictive text view (auto-complete), it inserts "The" into the view by three calls to this method. Parameters passed for each call:

  • range: {0,0} text: @"The"
  • range: {0,0} text: @"The"
  • range: {3,0} text: @" "

The space that I can understand; but why insert "The" twice?

+7
objective-c ios8 uitextview
source share
2 answers

I have the same problem. It seems that with smart text, setting textView.text in this delegate method calls the delegate method again (this only happens with smart text, as far as I know).

I fixed it by simply changing my textView changes with guard:

 private var hack_shouldIgnorePredictiveInput = false func textView(textView: UITextView!, shouldChangeTextInRange range: NSRange, replacementText text: String!) -> Bool { if hack_shouldIgnorePredictiveInput { hack_shouldIgnorePredictiveInput = false return false } hack_shouldIgnorePredictiveInput = true textView.text = "" // Modify text however you need. This will cause shouldChangeTextInRange to be called again, but it will be ignored thanks to hack_shouldIgnorePredictiveInput hack_shouldIgnorePredictiveInput = false return false } 
+11
source share

I changed the accepted answer from Richard Wable because, as JLust noted in the comment, this third space call threw me away.

I added

 private var predictiveTextWatcher = 0 

AND

 if predictiveTextWatcher == 1 { predictiveTextWatcher = 0 return false } if hack_shouldIgnorePredictiveInput { predictiveTextWatcher += 1 hack_shouldIgnorePredictiveInput = false return false } 

These are all pretty hacks, but better than nothing.

Best

0
source share

All Articles