I want to be able to replace some text in an UITextView programatically, so I wrote this method as an UITextView category:
- (void) replaceCharactersInRange:(NSR
After having stumbled over this issue and getting grey hair of it, I finally found a satisfying solution. It's a bit tacky, but it DOES work like a charm. The idea is to use the working copy&paste support that UITextView offers! I think you might be interested:
- (void)insertText:(NSString *)insert
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard];
// Clear the current pasteboard
NSArray *oldItems = [pboard.items copy];
pboard.items = nil;
// Set the new content to copy
pboard.string = insert;
// Paste
[self paste: nil];
// Restore pasteboard
pboard.items = oldItems;
[oldItems release];
}
EDIT: Of course you can customize this code to insert text at any position in the text view. Just set the selectedRange
before calling paste
.
There is actually no reason for any hacks or custom categories to accomplish this. You can use the built in UITextInput Protocol method replaceRange:withText:
. For inserting text you can simply do:
[textView replaceRange:textView.selectedTextRange withText:replacementText];
This works as of iOS 5.0. Undo works automatically and there are no weird scrolling issues.
Shouldn't it be
[[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length)
withString:[self.text substringWithRange:range]];
And you probably can remove the mutable string and just do,
self.text = [self.text stringByReplacingCharactersInRange:range withString:newText];
I've been having trouble with this for a long time. I finally realized that you have to make sure you register the undo operation BEFORE doing any changes to your text storage.