Skip to content

How to display sample SwiftData in SwiftUI with PreviewModifier

In this tutorial, we will explore how to display sample SwiftData in SwiftUI with PreviewModifier

Step 1: Define the Entity

First, we need to define a Task entity that we will use to store our task data in SwiftData.

import Foundation
import SwiftData

@Model
class Task {
    @Attribute(.unique) var id: UUID
    var title: String?
    var isCompleted: Bool

    init(id: UUID = UUID(), title: String? = nil, isCompleted: Bool = false) {
        self.id = id
        self.title = title
        self.isCompleted = isCompleted
    }
}

In this code, we define the Task model with an id, title, and isCompleted property. The @Model attribute is used to make this class a SwiftData model.

Step 2: Create the Task List View

Next, we’ll create a SwiftUI view that displays a list of tasks, each with a toggle for marking them as completed or not.

import SwiftUI
import SwiftData

struct TaskListView: View {
    @Query(sort: \Task.title) private var tasks: [Task]
    @Environment(\.modelContext) private var context
    
    var body: some View {
        List {
            ForEach(tasks) { task in
                HStack {
                    Text(task.title ?? "")
                        .font(.title2)
                        .foregroundColor(task.isCompleted ? .green : .black)
                    
                    Spacer()
                    
                    Toggle("", isOn: Bindable(task).isCompleted)
                   
                }
            }
            .onDelete(perform: deleteTask)
        }
        .task {
            
            for task in sampleTasks {
                context.insert(task)
            }
            
        }
        .navigationTitle("Tasks")
    }
    
    private func updateTaskCompletion(_ task: Task, newValue: Bool) {
        task.isCompleted = newValue
        try? context.save()
    }
    
    private func deleteTask(at offsets: IndexSet) {
        for index in offsets {
            context.delete(tasks[index])
        }
        try? context.save()
    }
}

In this view, each task can be marked as completed by toggling a switch, and we handle saving this state with SwiftData.

Step 3: Preview with SwiftData Context

To make the preview functional, we need to set up a SwiftData context. We’ll use the PreviewModifier protocol to create a shared context that holds some sample data.

import Foundation
import SwiftUI
import SwiftData

let sampleTasks = [
    Task(title: "Buy Groceries"),
    Task(title: "Walk the Dog", isCompleted: true),
    Task(title: "Complete SwiftUI Project")
]

struct SampleTaskData: PreviewModifier {
    static func makeSharedContext() throws -> ModelContainer {
        let container = try ModelContainer(for: Task.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))

        for task in sampleTasks {
            container.mainContext.insert(task)
        }
        
        return container
    }

    func body(content: Content, context: ModelContainer) -> some View {
        content.modelContainer(context)
    }
}

extension PreviewTrait where T == Preview.ViewTraits {
    static var sampleTaskData: Self = .modifier(SampleTaskData())
}

In this example, the SampleTaskData struct conforms to PreviewModifier, providing a shared SwiftData context with in-memory tasks for the preview.

Step 4: Add a Preview #Preview(traits:

Now, let’s create a dynamic preview

#Preview(traits: .sampleTaskData) {
    TaskListView()
}

Step 5. Add @Previewable to Preview

Now, we’ll use the @Previewable attribute inside the #Preview macro to interact with the Task completion status dynamically.

#Preview("Dynamic Task Preview") {
    @Previewable @State var isTaskCompleted = false
    let sampleTask = Task(title: "Complete SwiftUI Project", isCompleted: isTaskCompleted)
    
    return HStack {
        Text(sampleTask.title ?? "")
            .font(.title2)
            .foregroundColor(sampleTask.isCompleted ? .green : .black)
        
        Spacer()
        
        Toggle("", isOn: $isTaskCompleted)
    }
}

In this preview:

  • The @Previewable attribute tags the isTaskCompleted state variable.
  • This allows you to toggle the state of isTaskCompleted directly in the Xcode preview and see real-time changes.
  • The task’s completion status will update dynamically as you interact with the toggle in the preview.

This tutorial demonstrated how to display sample SwiftData in SwiftUI with PreviewModifier and @Previewable

Back To Top
Search