UndoManager in Swift 5 with example
Perform undo-redo actions in a more simple way
Updated on 29th April 2021, 10:15 AM GMT 5:30+
Check out my Card Saver to save your Credit and Debit cards securely.
- Developed in SwiftUI
- only [<1MB] in Size
https://apps.apple.com/US/app/id1565309672?l=en
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, Let’s explore it in details together.
- No, Don’t worry. Follow this article, you will learn everything about UndoManager.
Let’s understand the UndoManager,
- What is UndoManager?
- What are the benefits of UndoManager?
- Understand UndoManager with a real-life example.
- How does undo and redo works in UndoManager with almost zero efforts?
- Download full-example from Github link available at the bottom.
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 have seen 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.
Student.swift,
We have two properties name
and studyInClass
of type string.
We have one more static constant property allStudents
which holds the predefined students. We can consider allStudents
as a tiny database of our application, which can be accessed via Student.allStudents
.
StudentTableViewCell.swift
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.
StudentsListViewController.swift
In StudentsListViewController.swift,
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 operationbtnRedoDidTap(_ :)
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 classUndoManager
.
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 for undo and redo(undo of undo) actions on line number 83 and 90.
- Method
addNewStudentUndoActionRegister(at:)
used to register to undo the action ofaddNewStudent(at:)
operation. This method performs the undo ofaddNewStudent(at:)
means this will remove the last added student during undo operation. - Method
removeNewStudentUndoActionRegister(at:)
used to register to undo the action ofremoveNewStudent(at:)
operation. Undo ofremoveNewStudent(at:)
operation is the redo ofaddNewStudent(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 Github
.
Exercise
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.
Conclusion:
- 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
Liked this article?
Give claps and show your support. It doesn’t cost you anything to clap.