This project will teach you about creating and managing lists, implementing CRUD (Create, Read, Update, Delete) operations, and using ToolBar items in SwiftUI.
What We’re Building
We’ll create an app where users can:
- View a list of notes
- Create new notes
- Edit existing notes
- Delete notes
- Sort notes by date or title
Prerequisites
- Xcode installed on your Mac
- Basic understanding of Swift and SwiftUI
- Familiarity with @State and basic SwiftUI views
Step 1: Setting Up the Project
- Open Xcode and create a new project.
- Choose “App” under the iOS tab.
- Name your project “NoteTaker” and ensure SwiftUI is selected for the interface.
Step 2: Creating the Note Model
First, let’s create our Note model:
import Foundation struct Note: Identifiable, Codable { var id = UUID() var title: String var content: String var date: Date }
Step 3: Creating a Note Store
Now, let’s create a class to manage our notes:
import Foundation class NoteStore: ObservableObject { @Published var notes: [Note] = [] init() { loadNotes() } func addNote(_ note: Note) { notes.append(note) saveNotes() } func updateNote(_ note: Note) { if let index = notes.firstIndex(where: { $0.id == note.id }) { notes[index] = note saveNotes() } } func deleteNote(_ note: Note) { notes.removeAll { $0.id == note.id } saveNotes() } func saveNotes() { if let encoded = try? JSONEncoder().encode(notes) { UserDefaults.standard.set(encoded, forKey: "notes") } } func loadNotes() { if let data = UserDefaults.standard.data(forKey: "notes"), let decoded = try? JSONDecoder().decode([Note].self, from: data) { notes = decoded } } }
This NoteStore
class handles the CRUD operations and persists the data using UserDefaults
.
Step 4: Creating the Main View
Let’s create our main view with a list of notes:
import SwiftUI struct ContentView: View { @StateObject private var noteStore = NoteStore() @State private var showingAddNote = false @State private var sortOrder: SortOrder = .date enum SortOrder { case date, title } var body: some View { NavigationView { List { ForEach(sortedNotes) { note in NavigationLink(destination: NoteDetailView(note: note, noteStore: noteStore)) { VStack(alignment: .leading) { Text(note.title) .font(.headline) Text(note.date, style: .date) .font(.subheadline) .foregroundColor(.secondary) } } } .onDelete(perform: deleteNotes) } .navigationTitle("Notes") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { showingAddNote = true }) { Image(systemName: "plus") } } ToolbarItem(placement: .navigationBarLeading) { Menu { Button("Sort by Date") { sortOrder = .date } Button("Sort by Title") { sortOrder = .title } } label: { Image(systemName: "arrow.up.arrow.down") } } } .sheet(isPresented: $showingAddNote) { NoteDetailView(noteStore: noteStore) } } } var sortedNotes: [Note] { switch sortOrder { case .date: return noteStore.notes.sorted { $0.date > $1.date } case .title: return noteStore.notes.sorted { $0.title < $1.title } } } func deleteNotes(at offsets: IndexSet) { for index in offsets { noteStore.deleteNote(sortedNotes[index]) } } }
Step 5: Creating the Note Detail View
Now, let’s create a view for adding and editing notes:
import SwiftUI struct NoteDetailView: View { @Environment(\.presentationMode) var presentationMode @ObservedObject var noteStore: NoteStore @State private var title: String @State private var content: String var note: Note? init(note: Note? = nil, noteStore: NoteStore) { self.noteStore = noteStore self.note = note _title = State(initialValue: note?.title ?? "") _content = State(initialValue: note?.content ?? "") } var body: some View { NavigationView { Form { TextField("Title", text: $title) TextEditor(text: $content) } .navigationTitle(note == nil ? "New Note" : "Edit Note") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Save") { if let note = note { let updatedNote = Note(id: note.id, title: title, content: content, date: Date()) noteStore.updateNote(updatedNote) } else { let newNote = Note(title: title, content: content, date: Date()) noteStore.addNote(newNote) } presentationMode.wrappedValue.dismiss() } .disabled(title.isEmpty) } } } } }
Conclusion
You’ve built a functional Note Taking app using SwiftUI. In this tutorial, you’ve learned:
- How to implement CRUD operations in SwiftUI
- How to use
@StateObject
and@ObservedObject
for state management - How to persist data using
UserDefaults
- How to use
NavigationView
andNavigationLink
for navigation - How to implement sorting functionality
- How to use
ToolBar
items for additional functionality
This project serves as a great foundation for more complex productivity apps.