Why does InsertText from UITextInput breaks keyboard suggestions? - ios

So we recently had an issue with our Keyboard extension showing wrong suggestions in the accompanying app. We found out that the text returned from context (super.textDocumentProxy.documentContextBeforeInput) was all wrong and since its a build in apple component something must go wrong with text insertion. We had following implementation for inserting text:
if (replaceRange.length > 0) {
[self.textView.textStorage replaceCharactersInRange:replaceRange withString:selectedWord];
[textView setSelectedRange:NSMakeRange(newLocation, 0)]; //Place cursor after inserted word
} else {
[self.textView insertText:selectedWord];
}
Would return something like:
There. . .
While the real text would be something like:
There it was. It was a little test. Test of everything.

The issue was found to be with insertText apparently it will properly insert text but the Keyboard context will not be able to read the inserted text. Now the fix was simply to use the replaceCharactersInRange for both insertions (meaning no if / else clause):
[self.textView.textStorage replaceCharactersInRange:replaceRange withString:selectedWord];
[textView setSelectedRange:NSMakeRange(newLocation, 0)]; //Place cursor after inserted word
This solved the issue and has made us conclude that insertText doesn't work as intended. Note that this will only be an issue if suggestions are to be used in the text field.

Related

UIKeyInput with All Caps Keyboard

I have created a custom text input view and am trying to force the keyboard to show all caps on the keyboard; similar to a UITextField. Here is what I have tried, but it isn't working for me:
class CustomInput: UIView, UIKeyInput {
// UIKeyInput inherits this property
var autocapitalizationType: UITextAutocapitalizationType {
get { return .AllCharacters }
set { }
}
}
I hoped that overriding the variable and only allowing .AllCharacters would force the keyboard to all caps, but that isn't the case. Any ideas how I can get the keyboard to all caps?
I have this same problem in an app I'm currently working on. Have spent a fair amount of time trying to figure this out, especially since autocorrectionType and keyboardType both seem to work fine.
My current work-around is to make my custom view implement UITextInput instead of UIKeyInput, with dummy code for all unused properties and functions. Extremely ugly work-around but it's the only way I can get it to work, so I'm running with it.
Would be interested to see if anyone has insight into the underlying issue here.

Cursor issue while creating Custom keyboard with UIView

My requirement was to make a application specific keyboard i.e with a different theme and different key contents as compared to the default keyboard. But the way Apple states to implement keyboard requires user effort to add it through Settings->General->Keyboard which I don't want.
So, for that I tried to implement it using a UIView and making it the inputView for UITextView and it is working perfectly fine except for one issue. I added a functionality to add a linebreak in the textView. For that the code I used is
textView.text = "\(textView.text)\n"
Now, whenever I add a linebreak through keyboard, line is changed, but a new cursor appears to blink above the old cursor. I don't know how to get rid of that.
To explain the problem in a better way, here's a GIF image of the issue.
Please help.

UITextField clear glitch - text highlights, selection carets appear

I'm seeing a glitch in a UITextField when you tap on the clear button (the little X). Immediately before the text disappears, the selection carets appear (the vertical lines you move to select text) and then the text highlights as if it were selected. This only happens for an instant -- the highlight and carets flash on then immediately go away. The text does, in fact, clear -- the problem is that it's a distracting visual glitch.
Has anyone seen this?
Related question: Is there a notification posted or delegate method called somewhere when text is highlighted? I could use that to detect the flash. But, I can't seem to find anything...
I also experienced this issue, on iOS8. My class is observing UITextFieldTextDidChangeNotification. Although I didn't find the explanation of WHY it's happening I found the following UITextField delegate fixed it for me:
- (BOOL)textFieldShouldClear:(UITextField *)textField {
textField.text = nil;
return YES;
}
Just nil the textfield text on 'clear' - takes care of the visual glitch.

When set UITextField as FirstResponder programmatically, cause some weird actions on text editing

I have a UITextField with custom keyboard, basically like a calculator. I would like my keyboard show up by default, so i used [self.topInputTextField becomeFirstResponder]; in viewDidLoad, I think that's very common usage. However, it causes some very weird actions on my textfield.
When i set my textfield as the first responder in viewDidLoad, and every time after i done editing, the text will jump, and when i click another text field and and click the first text field again, the texts in the first text field sometimes shift down and disappear, but sometimes not. I feel it's very hard to describe, so i recorded a GIF image for it.
And the reason, that I am sure [self.topInputTextField becomeFirstResponder]; causing the issue, is when i comment that line of code out, everything back to normal. here is the GIF after i comment out that line:
that's vert strange to me, between 2 GIF file, the only change i did is comment out that line of code. I couldn't find any solution on SE. Any idea would be very appreciated.
Edit:
One more thing is I tried to change font, and font sizes, they all have similar strange behaviors.
*Edit 2:**
here is how i set up my textfield,i didn't do anything fancy
Try calling the keyboard in viewDidAppear, this method gets called after viewDidLoad. I assume it's because you should only call the keyboard on a loaded view that has appeared to the user, so if you call it before the view actually appears it will cause unexpected behaviour.
viewDidLoad is too early for calling this, the UI hasn't worked out which size your screen is, or even which orientation your device is in. It isn't yet a UI really... Try it in willAppearAnimated: ..

How to push key value into UITextView from custom keyboard in iOS

I am building a virtual keyboard for a UITextView. All works well, I can display the keyboard and remove the keyboard as well as display the keystrokes. I am using the "stringByReplacingCharactersInRange: withString" method to place the new keystroke into the text view. This works but since it is replacing the string each time, the entry point goes to the end of the string. This all makes sense, but is not very usable. I can fix this by doing checks in my code but there might be something better...
So my question is this; Is there a way to push the new key to the UITextView directly without modifying the UITextView's text property's string manually? The manual states that I will have to manage the target/action myself, but I was wondering if I've missed an action to call. It seems that the Apple Default keyboard must have a slick way of punching the keystroke into the object without the obvious number of checks that I will have to do to make the typing smooth.
Any help will be greatly appreciated.
Thanks,
Rob
Well, I didn't get any responses. So I figured out a way to do it so it is reasonable and simple. It's a matter of tracking the selected range. So when I wish to Backspace I use this technique.
NSRange currentRange = self.myTextView.selectedRange;
if (currentRange.length == 0) {
currentRange.location--;
currentRange.length++;
}
self.myTextView.text = [self.myTextView.text stringByReplacingCharactersInRange:currentRange withString:[NSString string]];
currentRange.length = 0;
self.myTextView.selectedRange = currentRange;
If I need to type a character this works.
NSRange currentRange = self.myTextView.selectedRange;
self.myTextView.text = [self.myTextView.text stringByReplacingCharactersInRange:currentRange withString:someCharacter];
currentRange.location++;
currentRange.length = 0;
self.myTextView.selectedRange = currentRange;
If anyone has a better way, I'd like to hear it.
Thanks,
Rob

Resources