Featuring: The Fart Button Universe Expanded 🌌💨
Welcome back, brave developer! 🧙♂️✨ If you thought saving farts was magical, get ready — today, we're supercharging the Fart Button App with relationships, advanced fetch requests, and performance tips.
We're building not just a fart database — but a whole fart multiverse. 🌌💥
📚 What You'll Learn
- How to model relationships in Core Data
- How to write advanced FetchRequests
- Performance tips to keep your app speedy 💨💨
🛠 New Plan: Fart Categories
Our new app idea:
- Different types of farts belong to Categories.
- A Category (e.g., "Epic", "Squeaky", "Stealth Mode") has many Farts.
- Each Fart belongs to one Category.
In Core Data lingo: One-to-Many Relationship.
💾 Updating the Data Model
Open Model.xcdatamodeld
:
- Add a new Entity ➡️ Name it
Category
. - Add attributes to
Category
:name: String
- Update
Fart
:- Add a Relationship:
- Name:
category
- Destination:
Category
- Type: To One
- Name:
- Add a Relationship:
- In
Category
, add a Relationship:- Name:
farts
- Destination:
Fart
- Type: To Many
- Name:
- Set inverse relationships:
-
category
⬅️➡️farts
-
Congrats! You just taught Core Data that farts are social beings. 🎓
🖥 Updated Fart Button UI
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
entity: Category.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Category.name, ascending: true)]
) private var categories: FetchedResults<Category>
var body: some View {
NavigationView {
List {
ForEach(categories) { category in
Section(header: Text(category.name ?? "Unknown Category")) {
ForEach(category.fartsArray) { fart in
Text(fart.soundName ?? "Mystery Fart")
}
}
}
}
.navigationTitle("💨 Fart Archive 💨")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: addSampleData) {
Label("Add Sample", systemImage: "plus")
}
}
}
}
}
private func addSampleData() {
let newCategory = Category(context: viewContext)
newCategory.name = "Epic Farts"
let fart1 = Fart(context: viewContext)
fart1.soundName = "MegaBlast.mp3"
fart1.timestamp = Date()
fart1.category = newCategory
let fart2 = Fart(context: viewContext)
fart2.soundName = "AtomicFart.mp3"
fart2.timestamp = Date()
fart2.category = newCategory
do {
try viewContext.save()
} catch {
print("😱 Failed to save sample data: \(error.localizedDescription)")
}
}
}
extension Category {
var fartsArray: [Fart] {
let set = farts as? Set<Fart> ?? []
return set.sorted { $0.timestamp ?? Date() < $1.timestamp ?? Date() }
}
}
Boom. You now have categorized farts. Elite developer status unlocked. 🏆
🎯 Advanced Fetching: Only Epic Farts, Please
Want to get only farts from "Epic Farts" category? 🔥
func fetchEpicFarts() -> [Fart] {
let request: NSFetchRequest<Fart> = Fart.fetchRequest()
request.predicate = NSPredicate(format: "category.name == %@", "Epic Farts")
request.sortDescriptors = [NSSortDescriptor(keyPath: \Fart.timestamp, ascending: true)]
do {
return try viewContext.fetch(request)
} catch {
print("😱 Error fetching epic farts: \(error.localizedDescription)")
return []
}
}
With this, your app filters the legendary explosions from the mundane ones. 🎺💥
⚡️ Core Data Performance Tips
-
Batch Size: Large datasets? Use
fetchBatchSize
to avoid loading too much into memory.
request.fetchBatchSize = 20
Faulting: Core Data lazy-loads objects — don’t worry if you see a "fault" — it's good for performance!
Background Contexts: For heavy operations (e.g., importing thousands of farts), use a background context so your UI doesn't freeze. 🧊
Indexes: Set Indexes on frequently queried fields like
timestamp
orsoundName
!
🧹 Cleaning Up: Deleting a Category
Want to delete a Category (and maybe all its farts)?
func deleteCategory(_ category: Category) {
viewContext.delete(category)
do {
try viewContext.save()
} catch {
print("😱 Failed to delete category: \(error.localizedDescription)")
}
}
Easy peasy. (And surprisingly sad if you're attached to your farts.) 😢
🎇 Final Challenge: Stretch Goals
- Create Custom Category Icons (💥 vs 🥷)
- Allow renaming Categories
- Sort Categories based on number of farts (MOST FARTS WINS! 🏆)
- Add audio playback when tapping a fart 🎧
Congratulations, Core Data Wizard! 🧙♀️💨
You just leveled up your Fart Button App into a relational database masterpiece. Your ancestors would be proud.
Until next time — stay classy, and keep coding! 💨👑