In SwiftUI development, a common question arises: Should you use structs or classes for your…
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 theisTaskCompleted
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
This Post Has 0 Comments