← Back to list

Enhancing SwiftUI Data Management with Realm

The ability to store data persistently and create an intuitive user interface has become vital in the dynamic world of iOS development…

Sandro Tola in OverApp · 2024-02-12 10:47 · 365 claps · 8.8 min read
#realmswift #swiftui #ios-development #software-development #programming
Open on Medium ↗
Wiki topics: UX · UI/UX Design BIZ · Business Strategy 💻 · Programming 📱 · Mobile Development

Enhancing SwiftUI Data Management with Realm

The ability to store data persistently and create an intuitive user interface has become vital in the dynamic world of iOS development. Realm, a lightweight and powerful local database has become one of the most popular tools for developers looking for an efficient way to manage data. Its real-time functionality and user-friendly API make it a default solution for iOS apps. Combined with SwiftUI, Realm opens up new ways to create adaptive and data-centric apps that require less code but bring more performance.

SwiftUI, with its declarative nature, has transformed how developers create interfaces for iOS. Its plain text syntax makes UI creation easier to read and maintain, while also offering a set of tools for constructing sophisticated and dynamic layouts. Nevertheless, the real power of an application is often found in how well it handles and displays information. This is where Realm steps in, providing a convenient way to save data and retrieve it whenever needed while synchronizing with the UI components of SwiftUI.

The combination of Realm and SwiftUI provides an eloquent approach for the developers. It provides the capability to develop dynamic app experiences, with data management at its core. This synergy reduces the development process and improves the performance and scalability of iOS applications.

In this article, we will delve into the strategic integration of Realm within the SwiftUI framework. We will explore how this combination not only streamlines the development process but also augments the performance and scalability of iOS applications. From conceptual discussions to a practical case study of a to-do list application, we aim to provide insights into effectively harnessing the power of Realm with SwiftUI. Whether crafting a basic task manager or a complex platform, mastering the integration of Realm and SwiftUI is a crucial skill in the contemporary iOS development toolkit.

The Evolution of Data Management in iOS Apps

The landscape of data management in iOS development has evolved significantly over the years, marked by a notable shift from traditional solutions like CoreData to modern alternatives like Realm. CoreData, Apple’s framework, has been a staple in iOS data persistence due to its deep integration with the iOS ecosystem and robustness in handling complex data models and relationships. However, its steep learning curve has often posed challenges for developers.

Enter Realm, a newer player in the field, known for its simplicity and speed. One of the key advantages of Realm over CoreData is its ease of use. Realm simplifies object creation and data manipulation, allowing developers to write less code compared to the more boilerplate-heavy CoreData. This simplicity does not come at the cost of performance; in fact, Realm often outperforms CoreData.

image taken from this article

image taken from this article

Best Practices to follow

When integrating Realm with SwiftUI, following certain best practices can significantly enhance the efficiency and effectiveness of your application development process. Here are three key best practices to consider:

  1. Reactive Data Binding: Realm’s live objects are perfectly suited for SwiftUI’s reactive UI paradigm. By leveraging SwiftUI’s @ObservedObject and @Published property wrappers, your UI can automatically update in response to changes in the underlying data. This seamless integration ensures that your UI always remains in sync with your database state, eliminating the need for manual refreshes.
  2. Data Model Management: Realm’s approach to data model management is highly intuitive. Its models can be directly incorporated into SwiftUI views, greatly simplifying the creation and updating of UI components based on your data models. This simplicity speeds up the development process and enhances the maintainability of your code.
  3. Efficient Data Transactions: Realm excels in handling efficient data transactions, which is critical for maintaining data integrity and performance. It’s important to structure your data transactions and updates carefully, particularly in SwiftUI where views may update frequently. Use Realm wisely to ensure data consistency and avoid performance bottlenecks.

Now, let’s explore a practical example by examining a To-Do List Application that I’ve developed. We’ll go through its setup and implementation, taking into account the principles and best practices previously discussed. This walkthrough will provide insights into how these concepts are applied in a real-world scenario.

Case Study: A (To-Do List) Application

**This Task Manager Application **is a practical and user-friendly tool designed to assist individuals in managing their daily tasks and responsibilities. At its core, the app serves the fundamental purpose of enhancing productivity and organizational skills. The simplicity of a to-do list app makes it an ideal candidate for demonstrating key concepts in app development, particularly when integrating advanced technologies.

This application stands as a nice example to showcase the integration of Realm with SwiftUI for several reasons. Firstly, it involves fundamental data operations like creating, reading, updating, and deleting tasks (CRUD), essential in understanding database management. Realm excels in handling these operations with efficiency and simplicity, making it a suitable choice for the underlying data structure of the app.

Secondly, the dynamic nature of a to-do list, with tasks being added, modified, or marked as complete, provides a perfect scenario to illustrate the reactive data binding capabilities of SwiftUI in conjunction with Realm. This integration allows for real-time updates in the user interface as the underlying data changes, a crucial feature for maintaining an up-to-date and responsive application.

The app is in the “empty” state. To add a task to our Database we can click on the “+” button.

As you can see, the display of the newly created task is instant. Let’s see the implementation.

//
//  AddNewTask.swift
//  TaskManager
//
//  Created by Sandro Tola on 07/02/24.
//

import SwiftUI
import RealmSwift

struct AddTaskView: View {
    @State private var taskName: String = ""
    @State private var taskType: String = ""
    @State private var startTime: Date = Calendar.current.startOfDay(for: Date())
    @State private var endTime: Date = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60)

    @Binding var showModal: Bool
    var body: some View {
        NavigationView {
            Form {
                TextField("Task Name", text: $taskName)
                TextField("Task Type", text: $taskType)
                DatePicker("Start Time", selection: $startTime, displayedComponents: .hourAndMinute)
                DatePicker("End Time", selection: $endTime, in: startTime..., displayedComponents: .hourAndMinute)
                Button("Save Task") {
                    saveTask()
                }
            }
            .navigationBarTitle("Add New Task", displayMode: .inline)
            .navigationBarItems(trailing: Button("Cancel") { showModal = false })
        }
    }

    private func saveTask() {
        // Format date to get hours and minutes
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm"

        // Prepare task to save
        let newTask = Task()
        newTask.name = taskName
        newTask.type = taskType
        newTask.startTime = formatter.string(from: startTime)
        newTask.endTime = formatter.string(from: endTime)

        // Call our Realm Manager to save the task in the local Database
        RealmManager.shared.addTask(newTask)

        // Close the modal
        showModal = false
    }
}

The AddTaskView struct is a SwiftUI view that serves as a user interface for adding new tasks. It has several state variables: taskName, taskType, startTime, and endTime, which are bound to form fields, allowing the user to input the name and type of the task, as well as to select a start and end time.

A “Save Task” button is provided to trigger the saveTask function. This function formats the dates to extract hours and minutes, creates a new Task object with the entered details, and then calls “RealmManager.shared.addTask(newTask)” to save this task to the Realm database. After saving, the modal is dismissed by setting showModal to false.

//
//  RealmManager.swift
//  TaskManager
//
//  Created by Sandro Tola on 07/02/24.
//

import RealmSwift

class RealmManager {
    // Singleton istance
    static let shared = RealmManager()

    // Realm istance
    private var realm: Realm

    // Start Realm
    private init() {
        do {
            realm = try Realm()
        } catch let error {
            fatalError("Realm can't be initialized: \(error.localizedDescription)")
        }
    }

    // Function to add a new Task to Realm
    func addTask(_ task: Task) {
        do {
            try realm.write {
                realm.add(task)
            }
        } catch let error {
            print("Error adding task: \(error.localizedDescription)")
        }
    }

    // Function to delete a Task from Realm
    func deleteTask(_ task: Task) {
        do {
            // Fetch the same task from the current Realm instance
            if let taskToDelete = realm.object(ofType: Task.self, forPrimaryKey: task.id) {
                try realm.write {
                    realm.delete(taskToDelete)
                }
            } else {
                print("Task not found or already deleted")
            }
        } catch let error {
            print("Error deleting task: \(error.localizedDescription)")
        }
    }

    // Function to edit a Task in Realm
    func updateTask(_ task: Task, with newTask: Task) {
        do {
            // Fetch the same task from the current Realm instance
            if let taskToUpdate = realm.object(ofType: Task.self, forPrimaryKey: task.id) {
                try realm.write {
                    taskToUpdate.name = newTask.name
                    taskToUpdate.type = newTask.type
                    taskToUpdate.startTime = newTask.startTime
                    taskToUpdate.endTime = newTask.endTime
                }
            } else {
                print("No Task with id \(task.id) found")
            }
        } catch let error {
            print("Error updating task: \(error.localizedDescription)")
        }
    }
}

The RealmManager class is responsible for managing the Realm database operations. It is designed as a singleton to provide a consistent point of access to the Realm instance. The “addTask” function takes a Task object and performs a write transaction on the Realm instance to add the task to the database. There are also functions for deleting (“deleteTask”) and updating (“updateTask”) tasks.

Once the task is added, “@ObservedResult ” gets the new Task List and displays it instantly.

As previously said, the app performs edit operations also:

struct MyTaskList: View {
    let tasks: [Task]
    @State private var activeTaskId: ObjectId?
    @Binding var showingAddTaskModal: Bool
    @State var showingEditTaskModal: Bool = false
    @State var selectedTask: Task = Task()

    var body: some View {
        VStack {
            HStack {
                Text("My Tasks")
                    .font(.largeTitle)
                    .bold()
                    .padding()
                Spacer()
                Button(action: {
                    showingAddTaskModal = true
                    activeTaskId = nil
                }) {
                    Image(systemName: "plus.circle.fill")
                        .resizable()
                        .frame(width: 30, height: 30)
                        .foregroundColor(.pink)
                }
                .padding()
            }

            if tasks.isEmpty {
                Text("Your work for the day is done.")
                    .font(.headline)
                    .bold()
                    .padding()
            } else {
                ScrollView(showsIndicators: false) {
                    VStack(spacing: 10) {
                        ForEach(tasks) { task in
                            TaskCard(
                                task: task,
                                activeTaskId: $activeTaskId,
                                onEdit: {
                                    selectedTask.id = task.id
                                    selectedTask.name = task.name
                                    selectedTask.type = task.type
                                    selectedTask.startTime = task.startTime
                                    selectedTask.endTime = task.endTime
                                    activeTaskId = nil
                                    showingEditTaskModal = true
                                },
                                onComplete: {
                                    activeTaskId = nil
                                    RealmManager.shared.deleteTask(task)
                                }
                            )
                            .onLongPressGesture {
                                activeTaskId = (activeTaskId == task.id) ? nil : task.id
                            }
                        }
                    }
                    .padding()
                }
            }
        }
        .onTapGesture {
            activeTaskId = nil
        }
        .sheet(isPresented: $showingEditTaskModal) {
            EditTaskView(task: selectedTask, showModal: $showingEditTaskModal)
        }
    }
}

Thanks to a Long Press Gesture on the Task Card the user can “select” a task.

Upon selection, the Task Card reveals two options, edit and complete, each represented by universally recognized icons — a pencil for edits and a checkmark for completion. Tapping the pencil icon invokes the editing mode. This is where the seamless integration of Realm and SwiftUI shines.

The EditTaskView modal slides into view, populated with the task’s current details fetched from the Realm database. Here, the user is presented with the familiar fields of task name, type, and the start and end times ripe for modification.

As the user makes adjustments and hits “Save”, the magic of Realm’s real-time database updates the records. Behind the scenes, the RealmManager class performs the heavy lifting. It accesses the current Realm instance, finds the task by its unique identifier, and executes a write transaction. The fields are updated with the new data, and upon completion, the modal dismisses itself, returning the user to their task list.

The beauty of this process lies in its fluidity — the user’s interaction with the task list is uninterrupted, and the updates appear to occur instantaneously. The reactive nature of SwiftUI means the UI is always a true reflection of the underlying data. There’s no need for a refresh button or a manual reload; the changes just appear, as if by magic.

Lastly, the user can select a Task and mark it as “completed”:

In this case, the checkmark button will just call the “deleteTask” from the Realm Manager.

Conclusion

In conclusion, the journey through the creation and refinement of this Task Manager Application has been an enlightening expedition into the possibilities of modern iOS application development. The seamless integration of Realm has demonstrated a significant reduction in the complexity typically associated with persistent local data storage and has showcased the dynamic capabilities of SwiftUI’s reactive user interface.

The exploration of functionalities like adding tasks in a few taps, editing them with ease, and finally marking them as complete with a satisfying tap illustrates the practicality and user-friendliness of combining Realm with SwiftUI. This case study serves as a testament to the powerful symbiosis between a database and a user interface, highlighting the ease with which developers can build responsive, data-driven applications.

Thank you for your time, and I will see you in my next article 😉.


메타데이터
post_id
82048307a2a3
slug
enhancing-swiftui-data-management-with-realm-82048307a2a3
url
https://insights.overapp.com/enhancing-swiftui-data-management-with-realm-82048307a2a3
canonical_url
https://insights.overapp.com/enhancing-swiftui-data-management-with-realm-82048307a2a3
author_url
https://medium.com/@sandro.tola
status
ok
fetched_at
2026-06-10 08:17:25