Creating a Simple Memo App with SwiftUI and SwiftData (Including Data Persistence)
I will outline the steps to create a simple memo app (including data persistence) using SwiftUI and SwiftData.
Overview
When developing an app with SwiftUI, I found the need for data persistence, so I will summarize the usage by implementing a simple memo app as a sample using SwiftData. While researching persistence in SwiftUI, Core Data frequently appeared, and initially, I intended to use Core Data.
However, when creating the project, I noticed the mention of "SwiftData" in the Storage section. Upon further investigation, it seems to be a newly introduced feature, announced at WWDC 2023. I would like to give it a try since it's a recently released feature.
As a side note, when it comes to new technologies, especially in a professional context, I prefer not to use them until there is sufficient information available. However, for personal projects, I adopt a policy of actively incorporating new technologies.
Overview of the App to Be Created
The goal is to implement the following features in the memo app: creation, display, and deletion of memos.
Source Code
https://github.com/tkugimot/EasyMemo
Summary of the implementation
Add the following files.
ファイル名 | 役割 |
---|---|
Domains/Memo/Memo | Memo Model for SwiftData |
Screens/MemoListScreen | This screen displays the source for viewing and deleting memos, as well as transitioning to the creation of new memos. |
Views/AddMemoView | This screen allows the addition of new memos. |
Implementation
Create project
I will create an app with the Product Name "EasyMemo" and specify SwiftData in the Storage. It will be created with a model called "Item" and a sample implementation that uses it. Please delete them as needed.
Create a model for the data to be saved
import Foundation
import SwiftData
@Model
final class Memo {
var content: String
var createdAt: Date
var updatedAt: Date
init(content: String) {
self.content = content
createdAt = Date()
updatedAt = Date()
}
}
Create AddMemoView
struct AddMemoView: View {
@Environment(\.modelContext) private var context
@Environment(\.presentationMode) var presentation
@State private var content: String = ""
var body: some View {
VStack {
Form {
TextField(
text: $content,
prompt: Text("Required"),
axis: .vertical
) {
Text("Content")
}
.lineLimit(5...10)
}
}
.navigationBarTitle("Add new memo")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {add()}) {
Text("Save")
}
}
}
}
private func add() {
let newMemo = Memo(content: content)
context.insert(newMemo)
// go back to previous page
presentation.wrappedValue.dismiss()
}
}
#Preview {
AddMemoView()
}
Create MemoListScreen
import SwiftUI
import SwiftData
struct MemoListScreen: View {
@Environment(\.modelContext) private var context
@Query private var memos: [Memo]
var body: some View {
NavigationView {
List {
ForEach(memos) { memo in
NavigationLink {
VStack(alignment: .leading) {
Text(memo.content)
.font(.title)
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading)
.padding()
}
.padding()
} label: {
Text(memo.content)
.font(.subheadline)
.frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/, alignment: .leading)
.lineLimit(1)
}
}
.onDelete(perform: { indexSet in
for index in indexSet {
delete(memo: memos[index])
}
})
}
.navigationTitle("Memo")
.navigationBarTitleDisplayMode(.automatic)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink(destination: AddMemoView()) {
Text("Add")
}
}
}
}
}
private func delete(memo: Memo) {
context.delete(memo)
}
}
#Preview {
MemoListScreen()
.modelContainer(for: Memo.self)
}
Modify ContentView
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
var body: some View {
MemoListScreen()
}
}
#Preview {
ContentView()
.modelContainer(for: Memo.self, inMemory: true)
}
Thoughts
Honestly, I was pleasantly surprised by the ease of use of SwiftData. There is virtually no boilerplate code, and I am impressed by its streamlined interface design. The recent Swift language, in general, seems highly implementable and well-organized, giving me a very positive outlook on app development at the moment. Thank you to everyone at Apple for these advancements.