Implementing Undo and Redo in a UItextview with Attributedtext

Implementing undo and redo in a UITextView with attributedText

Here's some sample code to handle undo/redo for a UITextView. Don't forget to update your undo/redo buttons state initially and after each change to the text.

class ViewController: UIViewController {

@IBOutlet weak var textView: UITextView!
@IBOutlet weak var undoButton: UIButton!
@IBOutlet weak var redoButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()

updateUndoButtons()
}

@IBAction func undo(_ sender: Any) {
textView.undoManager?.undo()
updateUndoButtons()
}

@IBAction func redo(_ sender: Any) {
textView.undoManager?.redo()
updateUndoButtons()
}

func updateUndoButtons() {
undoButton.isEnabled = textView.undoManager?.canUndo ?? false
redoButton.isEnabled = textView.undoManager?.canRedo ?? false
}
}

extension ViewController: UITextViewDelegate {

func textViewDidChange(_ textView: UITextView) {
updateUndoButtons()
}
}

Obviously you'll need to hook up the actions/outlets and the text view's delegate outlet in a storyboard

How to implement undo with NSTextview

From Cocoa Text Architecture Guide: Text Editing – Text Change Notifications and Delegate Messages:

In actually making changes to the text, you must ensure that the changes are properly performed and recorded by different parts of the text system. You do this by bracketing each batch of potential changes with shouldChangeTextInRange:replacementString: and didChangeText messages. These methods ensure that the appropriate delegate messages are sent and notifications posted. …

In my experience, that includes generating the relevant undo operation.

So, you would do:

if ([self.textView shouldChangeTextInRange:selectedRange replacementString:stringToReplace])
{
[[self.textView textStorage] beginEditing];
[[self.textView textStorage] replaceCharactersInRange:selectedRange withString:stringToReplace];
[[self.textView textStorage] endEditing];
[self.textView didChangeText];
}

iOS out of range crash when using shake to undo a paste into UITextView with overwritten shouldChangeCharactersInRange

If text for UITextView or UITextField is changed programatically while it is being changed the undo manager would not be updated and will keep track of wrong actions.
To avoid crash we should reset undo manager so it does not contain dirty actions.

[textField.undoManager removeAllActions];

Bold & Non-Bold Text In uitextView - iOS

You can use NSAttributedString to custom the string format:

public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.

var textV = new UITextView(new CGRect(100, 100, 300, 300));

var myMutableString = new NSMutableAttributedString("How ? \n Some text \n Who ? \n Some text");

var range1 = myMutableString.MutableString.LocalizedStandardRangeOfString(new NSString("How ?"));
var range2 = myMutableString.MutableString.LocalizedStandardRangeOfString(new NSString("Who ?"));

var range3 = myMutableString.MutableString.LocalizedStandardRangeOfString(new NSString("Some text"));

myMutableString.AddAttribute(UIStringAttributeKey.Font, UIFont.SystemFontOfSize(24), range1);
myMutableString.AddAttribute(UIStringAttributeKey.Font, UIFont.SystemFontOfSize(24), range2);

myMutableString.AddAttribute(UIStringAttributeKey.Font, UIFont.SystemFontOfSize(14), range3);

textV.AttributedText = myMutableString;
View.AddSubview(textV);
}

Here is the result:

Sample Image



Related Topics



Leave a reply



Submit