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.