¿Cómo puedo replace el text en UITextView con el soporte de NSUndoManager?

Quiero poder replace algún text en un UITextView de manera programática, así que escribí este método como una categoría UITextView:

- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)newText{ self.scrollEnabled = NO; NSMutableString *textStorage = [self.text mutableCopy]; [textStorage replaceCharactersInRange:range withString:newText]; //replace text but undo manager is not working well [[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) withString:[textStorage substringWithRange:range]]; NSLog(@"before replacing: canUndo:%d", [self.undoManager canUndo]); //prints YES self.text = textStorage; NSLog(@"after replacing: canUndo:%d", [self.undoManager canUndo]); //prints NO if (![self.undoManager isUndoing])[self.undoManager setActionName:@"replace characters"]; [textStorage release]; //new range: range.location = range.location + newText.length; range.length = 0; self.selectedRange = range; self.scrollEnabled = YES; } 

Funciona pero NSUndoManager deja de funcionar (parece que se reinicia) justo después de hacer self.text=textStorage He encontrado una API privada: -insertText:(NSString *) que puede hacer el trabajo, pero quién sabe si Apple va a aprobar mi aplicación si la uso. ¿Hay alguna forma de replace el text en UITextView con NSUndoManager Support? O tal vez me falta algo aquí?

En realidad, no hay ninguna razón para que los hacks o las categorías personalizadas lo logren. Puede usar el método de protocolo incorporado UITextInput replaceRange:withText: Para insert text, simplemente puede hacer lo siguiente:

 [textView replaceRange:textView.selectedTextRange withText:replacementText]; 

Esto funciona a partir de iOS 5.0. Undo funciona automáticamente y no hay problemas de desplazamiento extraños.

Después de haberme tropezado con este problema y haberlo perdido, finalmente encontré una solución satisfactoria. Es un poco hortera, pero funciona como un hechizo. ¡La idea es utilizar el soporte de copyr y pegar que ofrece UITextView! Creo que te puede interesar:

 - (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]; } 

EDITAR: Por supuesto, puede personalizar este código para insert text en cualquier position en la vista de text. Simplemente establezca el selectedRange antes de llamar a paste .

¿No debería ser

 [[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) withString:[self.text substringWithRange:range]]; 

Y es probable que pueda eliminar la cadena mutable y simplemente hacer,

 self.text = [self.text stringByReplacingCharactersInRange:range withString:newText];