UndoManager in Swift 5 with example
- Perform undo-redo actions in a more simple way
Updated on 18th April 2019, 10:48 PM GMT 5:30+
Have you heard about the UndoManager or NSUndoManager before? If your answer is,
- Yes, That’s great. You are one of very few developers who know about UndoManager.
- No, Don’t worry. Follow this article, you will learn everything about UndoManager.
I found that many of the developers required to implement undo/redo actions during development, usually in photo editing or video editing applications.
Suppose we are developing a photo editing application with Undo-Redo functionality in the editing screen. Consider that the user applied three filters on the existing image.
- Sepia effect filter
- Radial blur effect filter
- Dark light effect filter
Undo action will remove the last applied filter “Dark light effect filter”. Redo will again apply the last removed filter by undoing the action.
How will you implement this?
I found that many of the developers who are not aware of UndoManager implement this using array/stack. Implementation will result in complex conditional code and too much data overload, we need to keep the copy of the image after any filter applied.
We can solve this data overload and conditional complexity issue by using UndoManager easily.
What is UndoManager?
UndoManager/NSUndoManager are the classes that provide the undo-redo operations in a more easy, simple and convenient way. NSUndoManager is implemented in Object-C in Foundation Framework. UndoManager is the Swift implementation of NSUndoManager.
What are the benefits of UndoManager?
- We can perform undo-redo actions easily.
- We don’t need to maintain our own stack/array that usually ends up with the complex conditional logic for undo and redo actions.
Let’s understand UndoManager with below example,
We have only one screen having a list of students in table view and 3 buttons.
- Add button will add a new student in that list.
- Undo button will remove the last added student.
- Redo button will add the student, removed by undoing the action.
We have two properties
studyInClass of type string.
We have one more static constant property
allStudentswhich holds the predefined students. We can consider
allStudents as a tiny database of our application, which can be accessed via
StudentTableViewCell is a simple custom class to represent student cell in the list. This class has a data property named
‘student’, which is used to update cell UI.
line 23, We have property
students of array type having one student instance when the screen loads.
We have divided our view controller
StudentsListViewController in to multiple extensions to make it more readable.
StudentsListViewController.swift — First extension from line 34,
This extension will only handle IBActions triggered by User and enable/disable buttons.
btnAddNewStudentDidTap(_ :)will add a new student in the list and register its inverse action for undo.
btnUndoDidTap(_ :)will perform the undo operation
btnRedoDidTap(_ :)will perform the redo operation.
enableDisbaleActionsButtons()will enable the UI buttons if respective actions are possible. Add button will be disabled once we will have ten students on the list because we have only ten predefined student objects in our tiny database.
StudentsListViewController.swift — Second extension from line 62,
This extension will add a new student to list and remove a student from the list at a specific index.
StudentsListViewController.swift — Third extension from line 78,
This extension registers our undo and redo actions.
- Everything is dependent on the index when the current operation is performed.
You need to understand two important points here,
- Undo: inverse actions of the performed action
- Redo: inverse of the inverse of performed action, i.e. Undo of Undo is the Redo
- When you perform any action, you need to register to undo action using the method
registerUndo(withTarget:,handler:)on the instance of the class
Every view controller has one undoManager instance by default.
- In our above methods, we have used the default undoManager instance of the view controller to register to undo and redo(undo of undo) actions on line number 83 and 90.
addNewStudentUndoActionRegister(at:)used to register to undo the action of
addNewStudent(at:)operation. This method performs the undo of
addNewStudent(at:)means this will remove the last added student during undo operation.
removeNewStudentUndoActionRegister(at:)used to register to undo the action of
removeNewStudent(at:)operation. Undo of
removeNewStudent(at:)operation is the redo of
addNewStudent(at:)operation. Undo of Undo is Redo.
StudentsListViewController.swift — the Fourth extension from line 97,
This extension handles the table view related methods. Here we are using only two essential methods to create a table view in order to reduce complexity.
Download the full project from this
implementation of UndoManager in Swift5 Xcode 10.2 - hitendradeveloper/Simple-Undo-Redo-Examplegithub.com
Add swipe to delete actions in table view cell, implement undo-redo actions for swipe to delete.
We need to understand how action performs by UndoManager.
When you call
self.undoManager?.undo(), UndoManager triggers the block of undoing action registered using
registerUndo(withTarget: self, handler:) recently.
When you call
self.undoManager?.redo(), UndoManager triggers the block of undoing action registered using
registerUndo(withTarget: self, handler:) recently inside the last triggered undo block.
- Last registered action is treated as the latest Undo action
- Last registered action within the last triggered undo action is treated as the latest Redo action
Thanks for reading this article.
Liked this article?
You can give up to 50 claps: by long pressing the clap button.
if you enjoyed this article or learn something new, please tell your friends and share the love for this article.
@hitendrahckr is typing
Stay tuned, 2nd Part with group undo-redo actions is coming soon…
Follow my profile so you don’t miss any future article.
Where to go from here?
Read my latest series ‘Design patterns by Tutorials — The power of OOP’
Read another popular series ‘Protocol — The power of Swift’
Read my latest article
Programming Architectures — Redux | ReSwift
Patreon is empowering a new generation of creators. Support and engage with developer, artists, and creators as they live out their…www.patreon.com
Be my patron — request for any topic and sponsor future articles
More parts coming soon of this series…