14

I'm working on iOS 8 custom keyboard extension right now, and there are some issues in using UITextInputDelegate Methods.

Does this right: selectionWillChange: and selectionDidChange: methods should be called when user long-presses typing area? And textWillChange: and textDidChange: methods should be called whenever the text is literally changing?

Actually, what I observed is that, when I changed selection in text input area, textWillChange: and textDidChange: are called, and I cannot get a clue that the other two methods are called in what condition. If anyone knows about the usage of these delegate methods, please let me know.

Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
Tack-Gyu Lee
  • 448
  • 3
  • 11
  • Been pulling hairs over this too. I cannot get `selectionWillChange` `selectionDidChange` called. It is not clear from the (modest) documentation when exactly is it supposed to be called. _"when the selection has changed"_ is not exactly specific. I tried moving cursor, select, move selection, copy, paste. Did I miss something?? – bauerMusic Aug 06 '14 at 12:10
  • Totally agree. I read the documentation a hundred of times and still cannot figure out any clues. – Tack-Gyu Lee Aug 06 '14 at 16:49
  • @bauerMusic Got you a working solution, granted it isn't with the methods you wanted. http://stackoverflow.com/a/25225419/2057171 – Albert Renshaw Aug 10 '14 at 04:08
  • Bug. Still not working, but thankfully there *are* work arounds – Will Von Ullrich Jun 08 '18 at 17:59

2 Answers2

4

It's not working for me either... what I am currently doing is just using textWillChange and textDidChange which does get called, as you mentioned, when you change your selection... (they get called BEFORE and AFTER)

And then comparing the:
self.textDocumentProxy.documentContextBeforeInput
self.textDocumentProxy.documentContextAfterInput

From BEFORE (textWillChange) to the AFTER (textDidChange) to see if selection range or length changed at all.


Something like this (set the 4 NSStrings below in your .h file of course... haven't tested this exact snippet because I wrote it from scratch just now on SO.com but I'm sure the principle works if I made any errors)

- (void)textWillChange:(id<UITextInput>)textInput {
    beforeStringOfTextBehindCursor = self.textDocumentProxy.documentContextBeforeInput;
    beforeStringOfTextAfterCursor = self.textDocumentProxy.documentContextAfterInput;
}

- (void)textDidChange:(id<UITextInput>)textInput {
    afterStringOfTextBehindCursor = self.textDocumentProxy.documentContextBeforeInput;
    afterStringOfTextAfterCursor = self.textDocumentProxy.documentContextAfterInput;

    BOOL didSelectionChange = NO;

    if (![beforeStringOfTextBehindCursor isEqualToString:afterStringOfTextBehindCursor]) {
        didSelectionChange = YES;
    }

    if (![beforeStringOfTextAfterCursor isEqualToString:afterStringOfTextAfterCursor]) {
        didSelectionChange = YES;
    }

    if (didSelectionChange) {
        NSLog(@"Selection Changed!");
    }   
}
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
  • I filed a bug report to Apple a week ago and got a "test case" request from them, which I sent recently. Either this is not working as it should, or I missunderstood the function of the delegate, to which case, the documentations should be clearer and more specific. – bauerMusic Aug 10 '14 at 07:53
-1

I had the same problem with the functions specified in the UITextInput protocol not being called. The reason as far as I can discern is due to the fact that the inputDelegate is set at runtime. According to the ios docs:

The UIKit provides a private text input delegate, which it assigns at runtime to the inputDelegate property of the object whose class adopts the UITextInput protocol. link

The fix which works in my case is to reset the inputDelegate in the function:

textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
     replacementString:(NSString *)string

by the following line:

[myUITextField setInputDelegate:self];

where self implements the UITextInputDelegate protocol.

Daniel
  • 27
  • 1
  • 2
  • 1
    This answer is unclear, and appears to be wrong. The question is how to activate this protocol within an iOS8 keyboard extension, which functions only with the limited UITextInputDelegate methods. I can't find any UITextField available to set an input delegate to, or any way to override shouldChangeCharactersinRange. – SafeFastExpressive Nov 26 '14 at 20:50
  • I agree with Randy Hill. May be in a parallel universe there is UITextInput delegate available for this imaginary UITextfield the op is talking about, sadly not in this universe. – ThefunkyCoder Jan 23 '16 at 21:59