Skip to content

Instantly share code, notes, and snippets.

@nacho4d
Created July 12, 2012 08:24
Show Gist options
  • Save nacho4d/3096681 to your computer and use it in GitHub Desktop.
Save nacho4d/3096681 to your computer and use it in GitHub Desktop.
insert a string using UIKeyInput methods in UITextView in iOS5
- (void)insertString:(NSString *)inputKey
{
// Insert text (doing delegate calls appropiately)
NSRange changeRange = target.selectedRange;
if (!target.delegate || ([target.delegate respondsToSelector:@selector(textView:shouldChangeTextInRange:replacementText:)] &&
[target.delegate textView:target shouldChangeTextInRange:changeRange replacementText:inputKey])) {
// MarkedText could happen in multi-stage input languages
// In iOS5 several methods of UITextInput and UIKeyInput are badly implemented in UITextView
// setMarkedText:selectedRange: method seems to delete current markedText.
// Unmarking the text before inserting it is better than nothing.
UITextRange *markedTextRange = [target markedTextRange];
if (markedTextRange) {
if ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"5."]) {
// In iOS5 setMarkedText:selectedRange: is buggy and pretty useless in iOS5
// http://stackoverflow.com/questions/8066628/uitextinput-setmarkedtextselectedrange-not-working-cant-be
// rdar://10867047
[target unmarkText];
[target insertText:inputKey];
} else {
// According to Apple, rdar://10867047 is solved in iOS6b1
// Yeah setMarkedText:selectedRange: itself works but it brakes current
// multi-stage input session. In other words it still useless.
// Ideally below code would work but it doesn't :(
NSMutableString *markedText = [[target textInRange:markedTextRange] mutableCopy];
NSInteger markedTextStart = [target offsetFromPosition:target.beginningOfDocument toPosition:markedTextRange.start];
NSRange curSelection = [target selectedRange];
NSInteger loc = curSelection.location - markedTextStart;
[markedText insertString:inputKey atIndex:loc];
[target setMarkedText:markedText selectedRange:NSMakeRange(loc + inputKey.length, 0)];
[markedText release];
}
} else {
[target insertText:inputKey];
}
[[UIDevice currentDevice] playInputClick];
if ([target.delegate respondsToSelector:@selector(textViewDidChange:)]) {
[target.delegate textViewDidChange:target];
}
// Do not call textViewDidChangeSelection:, it is not called through text insertion/deletion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment