*Featuring: SnackAttack - Realtime Snack Voting App 🍪🍩🍕
Welcome, fearless developer! 🧙♂️✨ Today we dive into the exciting world of Firebase Firestore — Google's magic cloud database for realtime data sync!
And we won't just talk — we'll build an epic app: SnackAttack 🍿 — a real-time snack voting app where users battle it out over which snack rules supreme! 🥇🍕
📚 What You'll Learn
- What is Firebase Firestore?
- Setting up Firebase in your iOS project
- Creating, updating, and listening to realtime data
- Building a voting app with SwiftUI + Firestore
🔥 What Is Firestore?
- NoSQL cloud database by Google 🌎
- Realtime updates — changes show up instantly without refresh ⚡
- Offline support — keeps working even when you lose signal! 📶
- Cross-platform — mobile, web, and server ready 🚀
Perfect for any app that needs live data flying around! 🛫
🛠 Project Setup
- Create a new Xcode project (App template).
- Install Firebase SDK via Swift Package Manager:
- URL:
https://github.com/firebase/firebase-ios-sdk
- URL:
- Set up a Firebase project:
- Go to Firebase Console
- Create a new project.
- Add an iOS app (get your GoogleService-Info.plist).
- Download and drag
GoogleService-Info.plist
into Xcode.
- Configure Firebase in your app:
import Firebase
@main
struct SnackAttackApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
🍩 Designing the SnackAttack Database
In Firestore, we'll have a collection called snacks
:
Field | Type | Description |
---|---|---|
name | String | Name of the snack |
votes | Int | Number of votes |
Each snack is a document. Simple. Fast. Delicious. 🍩
✨ SwiftUI + Firestore Snack Voting App
import SwiftUI
import FirebaseFirestore
import FirebaseFirestoreSwift
struct Snack: Identifiable, Codable {
@DocumentID var id: String?
var name: String
var votes: Int
}
class SnackViewModel: ObservableObject {
@Published var snacks = [Snack]()
private var db = Firestore.firestore()
init() {
fetchData()
}
func fetchData() {
db.collection("snacks").order(by: "votes", descending: true)
.addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("😱 No documents: \(error?.localizedDescription ?? "unknown error")")
return
}
self.snacks = documents.compactMap { document -> Snack? in
try? document.data(as: Snack.self)
}
}
}
func addSnack(name: String) {
do {
_ = try db.collection("snacks").addDocument(from: Snack(name: name, votes: 0))
} catch {
print("😱 Error adding snack: \(error.localizedDescription)")
}
}
func vote(for snack: Snack) {
if let id = snack.id {
db.collection("snacks").document(id).updateData([
"votes": snack.votes + 1
])
}
}
}
struct ContentView: View {
@StateObject private var viewModel = SnackViewModel()
@State private var newSnackName = ""
var body: some View {
NavigationView {
VStack {
HStack {
TextField("New Snack", text: $newSnackName)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
viewModel.addSnack(name: newSnackName)
newSnackName = ""
}) {
Text("Add 🍪")
.padding(.horizontal)
}
}
.padding()
List(viewModel.snacks) { snack in
HStack {
Text(snack.name)
Spacer()
Text("\(snack.votes) 🍴")
Button(action: {
viewModel.vote(for: snack)
}) {
Text("Vote ✅")
}
}
}
}
.navigationTitle("SnackAttack 🍕")
}
}
}
⚡ How Realtime Sync Works
- Add a snack ➡️ Instantly shows for everyone.
- Vote for a snack ➡️ Instant update across all devices.
- New users see live leaderboard without manual refreshes.
Magic? Almost. 😎
🧠 Pro Tips for Firestore
- Security Rules: Lock down your database! Don’t leave it open to everyone. 🔒
- Indexes: Firestore automatically creates indexes but optimize when needed for performance.
- Batch Writes: Bundle multiple updates in one request.
- Offline Support: Firestore caches data — amazing for mobile!
🎯 Stretch Challenges for SnackAttack
- Add snack categories (Sweet 🍩, Savory 🍕, Healthy 🥗).
- Show snack pictures with
Firebase Storage
. - Sort by most recently added snacks.
- Add user authentication to track who voted.
Congratulations, Realtime Rockstar! 🌟
You built a cloud-connected, real-time updating app that syncs delicious snack battles across the globe. 🌍🍕
Keep coding, keep shipping, and remember: the snack must go on! 🚀🍪🍩🍕
Let me know if you want a bonus follow-up tutorial where we add user login with Firebase Authentication so voters can only vote once! 🎯🎟️