Learning iOS Development

Implementing Undo/Redo with Memento Design Pattern in Swift

Make your code more maintainable and flexible with Memento Design Pattern

Shashank Thakur
Mobile App Development Publication

--

Photo by Juan Rumimpunu on Unsplash

Design patterns play a pivotal role in software development, helping developers create clean, maintainable, and efficient code. One such design pattern is the Memento pattern, which falls under the category of behavioral patterns. The Memento pattern is all about capturing an object’s internal state without violating encapsulation and allowing it to be restored later. In this blog, we will explore the Memento design pattern in the context of Swift, a popular programming language for iOS and macOS app development.

What is the Memento Design Pattern?

The Memento pattern is a behavioral design pattern that enables you to capture and externalize an object’s internal state so that the object can be restored to this state later. It is often used to implement features like undo functionality or to save and restore an object’s state.

The primary components of the Memento pattern are:

  1. Originator: This is the object whose state needs to be saved. It creates and retrieves Memento objects containing its internal state.
  2. Memento: The Memento object stores the state of the Originator. It has methods to get and set the state of the Originator.
  3. Caretaker: The Caretaker is responsible for keeping track of the Memento objects. It can request Memento objects from the Originator to save its state or to restore it.

Implementing the Memento Design Pattern in Swift

Now, let’s see how we can implement the Memento design pattern in Swift. Suppose we have a simple class, TextEditor, and we want to implement undo functionality for it.

class TextEditor {
var text: String

init(text: String) {
self.text = text
}

func createMemento() -> TextEditorMemento {
return TextEditorMemento(text: text)
}

func restore(fromMemento memento: TextEditorMemento) {
text = memento.text
}
}

struct TextEditorMemento {
let text: String
}

In this example, TextEditor is the Originator class, and TextEditorMemento is the Memento class. Here's how it works:

  1. The TextEditor class has a createMemento method that creates a TextEditorMemento object, which stores the current text.
  2. The restore method in the TextEditor class takes a TextEditorMemento and restores the text from it.

Now, let’s create a Caretaker class that will manage the Memento objects:

class TextEditorHistory {
var history: [TextEditorMemento] = []

func save(_ memento: TextEditorMemento) {
history.append(memento)
}

func undo(_ editor: TextEditor) {
if let lastMemento = history.popLast() {
editor.restore(fromMemento: lastMemento)
}
}
}

The TextEditorHistory class keeps a list of Memento objects. The save method is used to save Memento objects, and the undo method allows us to revert the text to a previous state.

Now, let’s use these classes to implement undo functionality:

let editor = TextEditor(text: "Hello, World!")
let history = TextEditorHistory()

history.save(editor.createMemento()) // Save the initial state

editor.text = "This is a Swift blog."
history.save(editor.createMemento()) // Save the modified state

editor.text = "Memento pattern in Swift"
history.undo(editor) // Revert to the previous state

print(editor.text) // Output: "This is a Swift blog."

Conclusion

The Memento design pattern is a valuable tool for implementing features like undo functionality and state management in Swift applications. By encapsulating the object’s state and using the Memento pattern, you can make your code more maintainable and flexible. It’s essential to understand and apply design patterns like the Memento pattern to write clean, efficient, and organized code in Swift and other programming languages.

--

--