SlideShare a Scribd company logo
Building Swi
ft
UI Apps with
Firebase
Peter Friese, Developer Advocate, Google
@pete
rf
riese
Agenda
@pete
rf
riese
🎉


Demo
🔥


Firebase
🍏


Swi
ft
UI
🎓


Resources
Demo 1


JewelCase - A movie tracking app
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and Firebase
A declarative way to build your UI
Be
tt
er state management
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
Swift UI Views
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
Swift UI Views
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
struct SimpleList: View {

var movies = testData

var body: some View {

List(movies) { item in

HStack(alignment: .top) {

Image(item.coverImageName)

.resizable()

.aspectRatio(contentMode: .fit)

.frame(width: 100, height: 100, 

alignment: .center)

VStack(alignment: .leading) {

Text(item.title)

Text(item.subTitle)

}

}

}

}

}
Swift UI Views
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and Firebase
Improve app quality
Crashlytics
Performance
Monitoring
Test Lab
App Distribution
Grow your app
Analytics
Predictions
Cloud
Messaging
Remote
Config
A/B Testing
Dynamic


Links
In-app
Messaging
Build better apps
Auth
Cloud
Functions
Cloud
Firestore
Hosting
ML Kit
Realtime


Database
Cloud
Storage
bit.ly/what-is-firebase
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and Firebase
One-Time FetchesOffline ModeEffortless Syncing
Document
bird_type:


airspeed:


coconut_capacity:


isNative:


icon:


vector:


distances_traveled:
"swallow"

 42.733


0.62

false


<binary data>




{x: 36.4255,


y: 25.1442,


z: 18.8816


[42, 39, 12,
42]
Collection
collection("restaurants").


where("city", "
=
=
", "Cairo").


orderBy(“rating”, "desc").limit(10)
Here ya go!
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}

/
/
Elsewhere, fetch our data:


db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}
Fetching Data from Firestore
Saving Data to Firestore
let db = Firestore.firestore()


do {


_ = try db.collection(“movies")


.addDocument(from: movie)


}


catch {


print(“Error: (error.localizedDescription).")


}


Saving Data to Firestore
let db = Firestore.firestore()


do {


_ = try db.collection(“movies")


.addDocument(from: movie)


}


catch {


print(“Error: (error.localizedDescription).")


}


Saving Data to Firestore
&
Architecture
Architecture - MVVM
/
/
Model


struct Movie: Codable, Identifiable {

@DocumentID var id: String?

var title: String

var releaseDate: Date

var rating: Double

}
Architecture: Model
class MovieViewModel: ObservableObject {

@Published var movies = [Movie]()

private var db = Firestore.firestore()

func subscribe() {

db.collection("movies").addSnapshotListener { (querySnapshot, error) in

guard let documents = querySnapshot
?
.
documents else { return }



self.movies = documents.compactMap { queryDocumentSnapshot in

try? queryDocumentSnapshot.data(as: Movie.self)

}

}

}

}
Architecture: ViewModel
struct SimpleMovieList: View {

@StateObject var viewModel = MovieViewModel()



var body: some View {

List(viewModel.movies) { item in

Image(item.coverImageName)

VStack(alignment: .leading) {

Text(item.title)

Text(item.releaseDate.asString())

}

}

}

}
Architecture: View
Demo 2


JewelCase - A movie tracking app
h
tt
ps://github.com/pete
rf
riese/jewelcase
h
tt
ps://pete
rf
riese.dev
Thanks! Peter Friese, Developer Advocate, Google
@pete
rf
riese
h
tt
ps://pete
rf
riese.dev


h
tt
ps://medium.com/@pete
rf
riese




h
tt
ps://medium.com/
fi
rebase-developers


h
tt
ps://stackove
rf
low.com/questions/tagged/swi
ft
ui+
fi
rebase


h
tt
ps://github.com/
fi
rebase/
fi
rebase-ios-sdk
The End.
Backup
Data Flow
Data Flow
• Prope
rt
ies


• @State


• @Binding


• @ObservedObject


• @StateObject (✨ new in Swi
ft
UI 2)


• @EnvironmentObject


• Sarah Reichelt: Swi
ft
UI Data Flow


(bit.ly/Swi
ft
UIDataFlow)
Unsure which one to use?
struct DetailsView: View {

let movie: Movie



var body: some View {

ScrollView(.vertical) {

VStack(alignment: .leading) {

Text(movie.title).font(.title)

Text(movie.description).font(.body)

}

.padding()

}

.edgesIgnoringSafeArea(.all)

.background(Color(UIColor.secondarySystemBackground)

.edgesIgnoringSafeArea(.all))

}

}
Data Flow - Prope
rt
y
struct DetailsView: View {

let movie: Movie



var body: some View {

ScrollView(.vertical) {

VStack(alignment: .leading) {

Text(movie.title).font(.title)

Text(movie.description).font(.body)

}

.padding()

}

.edgesIgnoringSafeArea(.all)

.background(Color(UIColor.secondarySystemBackground)

.edgesIgnoringSafeArea(.all))

}

}
Data Flow - Prope
rt
y
Use for data thatdoesn’t change
struct GridView: View {

let movies: [Movie]



@State private var selection: Movie? = nil



var body: some View {

LazyVGrid(columns: columns, spacing: 20) {

ForEach(movies) { movie in

if (movie.id
!
=
selection
?
.
id) {

CardView(movie: movie)

.onTapGesture { select(movie) }

.matchedGeometryEffect(id: movie.id, in: ns)

}

else {

CardView(movie: movie)

.opacity(0)

}
Data Flow - @State
struct GridView: View {

let movies: [Movie]



@State private var selection: Movie? = nil



var body: some View {

LazyVGrid(columns: columns, spacing: 20) {

ForEach(movies) { movie in

if (movie.id
!
=
selection
?
.
id) {

CardView(movie: movie)

.onTapGesture { select(movie) }

.matchedGeometryEffect(id: movie.id, in: ns)

}

else {

CardView(movie: movie)

.opacity(0)

}
Data Flow - @State
struct GridView: View {

let movies: [Movie]



@State private var selection: Movie? = nil



var body: some View {

LazyVGrid(columns: columns, spacing: 20) {

ForEach(movies) { movie in

if (movie.id
!
=
selection
?
.
id) {

CardView(movie: movie)

.onTapGesture { select(movie) }

.matchedGeometryEffect(id: movie.id, in: ns)

}

else {

CardView(movie: movie)

.opacity(0)

}
Data Flow - @State
Use for UI state
struct DiscoverMoviesView: View {

@StateObject var viewModel = DiscoverViewModel()

@Environment(.presentationMode) var presentationMode

@EnvironmentObject var movieStore: MovieStore



var body: some View {

NavigationView {

VStack {

SearchBar(text: $viewModel.searchText)



List {

ForEach(viewModel.tmdbMovies) { item in

Data Flow - @StateObject
struct DiscoverMoviesView: View {

@StateObject var viewModel = DiscoverViewModel()

@Environment(.presentationMode) var presentationMode

@EnvironmentObject var movieStore: MovieStore



var body: some View {

NavigationView {

VStack {

SearchBar(text: $viewModel.searchText)



List {

ForEach(viewModel.tmdbMovies) { item in

Data Flow - @StateObject
Use for viewmodels
struct DiscoverMoviesView: View {

@EnvironmentObject var movieStore: MovieStore



func addMovie(movie: TMDBMovie) {

print("Adding (movie.title)")



let newMovie = Movie(from: movie)

movieStore.addMovie(newMovie)



dismiss()

}



}

Data Flow - @EnvironmentObject
struct DiscoverMoviesView: View {

@EnvironmentObject var movieStore: MovieStore



func addMovie(movie: TMDBMovie) {

print("Adding (movie.title)")



let newMovie = Movie(from: movie)

movieStore.addMovie(newMovie)



dismiss()

}



}

Data Flow - @EnvironmentObject
Use for passingstuff down
Se
tt
ing up Firebase for Swi
ft
UI 2
import SwiftUI

import Firebase

@main

struct JewelCaseApp: App {

@StateObject var movieStore = MovieStore()



init() {

FirebaseApp.configure()

}



var body: some Scene {

WindowGroup {

ContentView()

.environmentObject(movieStore)

}

}

}

Sett ing up Firebase for Swi
ft
UI 2
😱 No more
AppDelegate
import SwiftUI

import Firebase

@main

struct JewelCaseApp: App {

@StateObject var movieStore = MovieStore()



init() {

FirebaseApp.configure()

}



var body: some Scene {

WindowGroup {

ContentView()

.environmentObject(movieStore)

}

}

}

Sett ing up Firebase for Swi
ft
UI 2
Let’s use theinitialiser
import SwiftUI

import Firebase

@main

struct JewelCaseApp: App {

@StateObject var movieStore = MovieStore()



init() {

FirebaseApp.configure()

}



var body: some Scene {

WindowGroup {

ContentView()

.environmentObject(movieStore)

}

}

}

Sett ing up Firebase for Swi
ft
UI 2

More Related Content

What's hot (20)

PPTX
02 computer parts and ports
Melchor Balolong
 
PPT
Steps to install motherboard
dipaknandankar
 
PDF
Ceguera moral. la pérdida de sensibilidad en la modernidad líquida paidós
JORGEJAREDPLATASCURI
 
PPTX
Automatic Bottle filling and Capping using PLC
Navin Kumar Manoharan
 
PPTX
Cmos
mohan p
 
PPT
Chapter 2 Power Supply
askme
 
PPTX
Modbus RTU RS-485 مودباس بالعربي
EssosElectronic
 
PPT
Basic plc
mnamky
 
PDF
PLC y Electroneumática: Automatismos industriales por Julián Rodríguez Fernán...
SANTIAGO PABLO ALBERTO
 
PDF
Simens plc training. simatic working-with-step-7
SAIL,Rourkela steel plant.Rourkela.
 
PPTX
How to build up a Desktop Computer.pptx
Minhazul Abedin Munna
 
PPTX
Plc example presentation
Roshit Kadiru
 
PPT
Exposicion de bios alvaro v
ALVARO15TORO
 
PPTX
DCS
Priyesh vJ
 
PDF
libro-adultos-tdah.pdf
ssuser99a3d9
 
PDF
InTouch HMI SCADA
Wonderware United Kingdom
 
DOCX
Errores del scanner
saracastrejongalvan
 
PDF
Yokogawa cs3000
WALIEDDINE AISSASNOU
 
DOCX
TRANING REPORT ON PLC SCADA and AUTOMATION
Vikash Ranjan
 
DOC
Fuentes de alimentacion at y atx
Arturo Iglesias Castro
 
02 computer parts and ports
Melchor Balolong
 
Steps to install motherboard
dipaknandankar
 
Ceguera moral. la pérdida de sensibilidad en la modernidad líquida paidós
JORGEJAREDPLATASCURI
 
Automatic Bottle filling and Capping using PLC
Navin Kumar Manoharan
 
Cmos
mohan p
 
Chapter 2 Power Supply
askme
 
Modbus RTU RS-485 مودباس بالعربي
EssosElectronic
 
Basic plc
mnamky
 
PLC y Electroneumática: Automatismos industriales por Julián Rodríguez Fernán...
SANTIAGO PABLO ALBERTO
 
Simens plc training. simatic working-with-step-7
SAIL,Rourkela steel plant.Rourkela.
 
How to build up a Desktop Computer.pptx
Minhazul Abedin Munna
 
Plc example presentation
Roshit Kadiru
 
Exposicion de bios alvaro v
ALVARO15TORO
 
libro-adultos-tdah.pdf
ssuser99a3d9
 
InTouch HMI SCADA
Wonderware United Kingdom
 
Errores del scanner
saracastrejongalvan
 
Yokogawa cs3000
WALIEDDINE AISSASNOU
 
TRANING REPORT ON PLC SCADA and AUTOMATION
Vikash Ranjan
 
Fuentes de alimentacion at y atx
Arturo Iglesias Castro
 

Similar to Building Apps with SwiftUI and Firebase (20)

PDF
Rapid Application Development with SwiftUI and Firebase
Peter Friese
 
PDF
Rapid Application Development with SwiftUI and Firebase
Peter Friese
 
PDF
Firebase for Apple Developers - SwiftHeroes
Peter Friese
 
PDF
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
Peter Friese
 
PDF
Android architecture components with cloud firestore
Pankaj Rai
 
PDF
Firebase for Apple Developers
Peter Friese
 
PDF
Firebase & SwiftUI Workshop
Peter Friese
 
PDF
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Chris Adamson
 
PDF
Firebase: Totally Not Parse All Over Again (Unless It Is)
Chris Adamson
 
PPTX
Firebase - A real-time server
Aneeq Anwar
 
PDF
Writing Your App Swiftly
Sommer Panage
 
PDF
App development with constraint layout, kotlin &amp; firebase
Pankaj Rai
 
PDF
How to become an Android dev starting from iOS (and vice versa)
Giuseppe Filograno
 
PDF
Coding Defensively Against APIs iOSoHo 2015.03 March - Michael Sanderson
Michael Sanderson
 
PDF
Best Practices
Roy Marmelstein
 
PDF
meetstore5.pdf
Mike Nakhimovich
 
PDF
Cesar Valiente "Unidirectional architecture on Android with Kotlin"
IT Event
 
PDF
iOS Swift application architecture
Romain Rochegude
 
PDF
Deep Dive Into Swift
Sarath C
 
PPTX
Building a Google Cloud Firestore API with dotnet core
Mike Melusky
 
Rapid Application Development with SwiftUI and Firebase
Peter Friese
 
Rapid Application Development with SwiftUI and Firebase
Peter Friese
 
Firebase for Apple Developers - SwiftHeroes
Peter Friese
 
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
Peter Friese
 
Android architecture components with cloud firestore
Pankaj Rai
 
Firebase for Apple Developers
Peter Friese
 
Firebase & SwiftUI Workshop
Peter Friese
 
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Chris Adamson
 
Firebase: Totally Not Parse All Over Again (Unless It Is)
Chris Adamson
 
Firebase - A real-time server
Aneeq Anwar
 
Writing Your App Swiftly
Sommer Panage
 
App development with constraint layout, kotlin &amp; firebase
Pankaj Rai
 
How to become an Android dev starting from iOS (and vice versa)
Giuseppe Filograno
 
Coding Defensively Against APIs iOSoHo 2015.03 March - Michael Sanderson
Michael Sanderson
 
Best Practices
Roy Marmelstein
 
meetstore5.pdf
Mike Nakhimovich
 
Cesar Valiente "Unidirectional architecture on Android with Kotlin"
IT Event
 
iOS Swift application architecture
Romain Rochegude
 
Deep Dive Into Swift
Sarath C
 
Building a Google Cloud Firestore API with dotnet core
Mike Melusky
 
Ad

More from Peter Friese (20)

PDF
Building Reusable SwiftUI Components
Peter Friese
 
PDF
Building Reusable SwiftUI Components
Peter Friese
 
PDF
6 Things You Didn't Know About Firebase Auth
Peter Friese
 
PDF
Five Things You Didn't Know About Firebase Auth
Peter Friese
 
PDF
Building High-Quality Apps for Google Assistant
Peter Friese
 
PDF
Building Conversational Experiences with Actions on Google
Peter Friese
 
PDF
Building Conversational Experiences with Actions on Google
Peter Friese
 
PDF
What's new in Android Wear 2.0
Peter Friese
 
PDF
Google Fit, Android Wear & Xamarin
Peter Friese
 
PDF
Introduction to Android Wear
Peter Friese
 
PDF
Google Play Services Rock
Peter Friese
 
PDF
Introduction to Android Wear
Peter Friese
 
PDF
Google+ for Mobile Apps on iOS and Android
Peter Friese
 
PDF
Cross-Platform Authentication with Google+ Sign-In
Peter Friese
 
PDF
Bring Back the Fun to Testing Android Apps with Robolectric
Peter Friese
 
PDF
Do Androids Dream of Electric Sheep
Peter Friese
 
PDF
Java based Cross-Platform Mobile Development
Peter Friese
 
PDF
CouchDB Mobile - From Couch to 5K in 1 Hour
Peter Friese
 
PDF
RestKit - From Zero to Hero
Peter Friese
 
PDF
Fake it til you make it
Peter Friese
 
Building Reusable SwiftUI Components
Peter Friese
 
Building Reusable SwiftUI Components
Peter Friese
 
6 Things You Didn't Know About Firebase Auth
Peter Friese
 
Five Things You Didn't Know About Firebase Auth
Peter Friese
 
Building High-Quality Apps for Google Assistant
Peter Friese
 
Building Conversational Experiences with Actions on Google
Peter Friese
 
Building Conversational Experiences with Actions on Google
Peter Friese
 
What's new in Android Wear 2.0
Peter Friese
 
Google Fit, Android Wear & Xamarin
Peter Friese
 
Introduction to Android Wear
Peter Friese
 
Google Play Services Rock
Peter Friese
 
Introduction to Android Wear
Peter Friese
 
Google+ for Mobile Apps on iOS and Android
Peter Friese
 
Cross-Platform Authentication with Google+ Sign-In
Peter Friese
 
Bring Back the Fun to Testing Android Apps with Robolectric
Peter Friese
 
Do Androids Dream of Electric Sheep
Peter Friese
 
Java based Cross-Platform Mobile Development
Peter Friese
 
CouchDB Mobile - From Couch to 5K in 1 Hour
Peter Friese
 
RestKit - From Zero to Hero
Peter Friese
 
Fake it til you make it
Peter Friese
 
Ad

Recently uploaded (20)

PDF
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
PDF
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
PPTX
Prompt Like a Pro. Leveraging Salesforce Data to Power AI Workflows.pptx
Dele Amefo
 
PPTX
From spreadsheets and delays to real-time control
SatishKumar2651
 
PPTX
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
 
PDF
SAP Firmaya İade ABAB Kodları - ABAB ile yazılmıl hazır kod örneği
Salih Küçük
 
PDF
Dipole Tech Innovations – Global IT Solutions for Business Growth
dipoletechi3
 
PDF
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
PPTX
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
 
PDF
Best Web development company in india 2025
Greenusys
 
PDF
TheFutureIsDynamic-BoxLang witch Luis Majano.pdf
Ortus Solutions, Corp
 
PDF
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
PDF
ERP Consulting Services and Solutions by Contetra Pvt Ltd
jayjani123
 
PDF
Ready Layer One: Intro to the Model Context Protocol
mmckenna1
 
PDF
Everything you need to know about pricing & licensing Microsoft 365 Copilot f...
Q-Advise
 
PDF
NPD Software -Omnex systems
omnex systems
 
PDF
intro_to_cpp_namespace_robotics_corner.pdf
MohamedSaied877003
 
PPTX
Build a Custom Agent for Agentic Testing.pptx
klpathrudu
 
PPTX
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
PPTX
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
Prompt Like a Pro. Leveraging Salesforce Data to Power AI Workflows.pptx
Dele Amefo
 
From spreadsheets and delays to real-time control
SatishKumar2651
 
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
 
SAP Firmaya İade ABAB Kodları - ABAB ile yazılmıl hazır kod örneği
Salih Küçük
 
Dipole Tech Innovations – Global IT Solutions for Business Growth
dipoletechi3
 
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
 
Best Web development company in india 2025
Greenusys
 
TheFutureIsDynamic-BoxLang witch Luis Majano.pdf
Ortus Solutions, Corp
 
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
ERP Consulting Services and Solutions by Contetra Pvt Ltd
jayjani123
 
Ready Layer One: Intro to the Model Context Protocol
mmckenna1
 
Everything you need to know about pricing & licensing Microsoft 365 Copilot f...
Q-Advise
 
NPD Software -Omnex systems
omnex systems
 
intro_to_cpp_namespace_robotics_corner.pdf
MohamedSaied877003
 
Build a Custom Agent for Agentic Testing.pptx
klpathrudu
 
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 

Building Apps with SwiftUI and Firebase

  • 1. Building Swi ft UI Apps with Firebase Peter Friese, Developer Advocate, Google @pete rf riese
  • 3. Demo 1 JewelCase - A movie tracking app
  • 6. A declarative way to build your UI
  • 8. struct ContentView: View { var body: some View { Text("Hello, World!") } } Swift UI Views
  • 9. struct ContentView: View { var body: some View { Text("Hello, World!") } } Swift UI Views
  • 10. struct ContentView: View { var body: some View { Text("Hello, World!") } } Swift UI Views
  • 11. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 12. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 13. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 14. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 15. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 16. struct SimpleList: View { var movies = testData var body: some View { List(movies) { item in HStack(alignment: .top) { Image(item.coverImageName) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100, alignment: .center) VStack(alignment: .leading) { Text(item.title) Text(item.subTitle) } } } } } Swift UI Views
  • 20. Improve app quality Crashlytics Performance Monitoring Test Lab App Distribution Grow your app Analytics Predictions Cloud Messaging Remote Config A/B Testing Dynamic Links In-app Messaging Build better apps Auth Cloud Functions Cloud Firestore Hosting ML Kit Realtime Database Cloud Storage bit.ly/what-is-firebase
  • 27. Fetching Data from Firestore
  • 28. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 29. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 30. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 31. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 32. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 33. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } / / Elsewhere, fetch our data: db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } Fetching Data from Firestore
  • 34. Saving Data to Firestore
  • 35. let db = Firestore.firestore() do { _ = try db.collection(“movies") .addDocument(from: movie) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 36. let db = Firestore.firestore() do { _ = try db.collection(“movies") .addDocument(from: movie) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 37. &
  • 40. / / Model struct Movie: Codable, Identifiable { @DocumentID var id: String? var title: String var releaseDate: Date var rating: Double } Architecture: Model
  • 41. class MovieViewModel: ObservableObject { @Published var movies = [Movie]() private var db = Firestore.firestore() func subscribe() { db.collection("movies").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot ? . documents else { return } self.movies = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Movie.self) } } } } Architecture: ViewModel
  • 42. struct SimpleMovieList: View { @StateObject var viewModel = MovieViewModel() var body: some View { List(viewModel.movies) { item in Image(item.coverImageName) VStack(alignment: .leading) { Text(item.title) Text(item.releaseDate.asString()) } } } } Architecture: View
  • 43. Demo 2 JewelCase - A movie tracking app
  • 46. Thanks! Peter Friese, Developer Advocate, Google @pete rf riese h tt ps://pete rf riese.dev h tt ps://medium.com/@pete rf riese 
 
 h tt ps://medium.com/ fi rebase-developers h tt ps://stackove rf low.com/questions/tagged/swi ft ui+ fi rebase h tt ps://github.com/ fi rebase/ fi rebase-ios-sdk
  • 50. Data Flow • Prope rt ies • @State • @Binding • @ObservedObject • @StateObject (✨ new in Swi ft UI 2) • @EnvironmentObject • Sarah Reichelt: Swi ft UI Data Flow 
 (bit.ly/Swi ft UIDataFlow)
  • 51. Unsure which one to use?
  • 52. struct DetailsView: View { let movie: Movie var body: some View { ScrollView(.vertical) { VStack(alignment: .leading) { Text(movie.title).font(.title) Text(movie.description).font(.body) } .padding() } .edgesIgnoringSafeArea(.all) .background(Color(UIColor.secondarySystemBackground) .edgesIgnoringSafeArea(.all)) } } Data Flow - Prope rt y
  • 53. struct DetailsView: View { let movie: Movie var body: some View { ScrollView(.vertical) { VStack(alignment: .leading) { Text(movie.title).font(.title) Text(movie.description).font(.body) } .padding() } .edgesIgnoringSafeArea(.all) .background(Color(UIColor.secondarySystemBackground) .edgesIgnoringSafeArea(.all)) } } Data Flow - Prope rt y Use for data thatdoesn’t change
  • 54. struct GridView: View { let movies: [Movie] @State private var selection: Movie? = nil var body: some View { LazyVGrid(columns: columns, spacing: 20) { ForEach(movies) { movie in if (movie.id ! = selection ? . id) { CardView(movie: movie) .onTapGesture { select(movie) } .matchedGeometryEffect(id: movie.id, in: ns) } else { CardView(movie: movie) .opacity(0) } Data Flow - @State
  • 55. struct GridView: View { let movies: [Movie] @State private var selection: Movie? = nil var body: some View { LazyVGrid(columns: columns, spacing: 20) { ForEach(movies) { movie in if (movie.id ! = selection ? . id) { CardView(movie: movie) .onTapGesture { select(movie) } .matchedGeometryEffect(id: movie.id, in: ns) } else { CardView(movie: movie) .opacity(0) } Data Flow - @State
  • 56. struct GridView: View { let movies: [Movie] @State private var selection: Movie? = nil var body: some View { LazyVGrid(columns: columns, spacing: 20) { ForEach(movies) { movie in if (movie.id ! = selection ? . id) { CardView(movie: movie) .onTapGesture { select(movie) } .matchedGeometryEffect(id: movie.id, in: ns) } else { CardView(movie: movie) .opacity(0) } Data Flow - @State Use for UI state
  • 57. struct DiscoverMoviesView: View { @StateObject var viewModel = DiscoverViewModel() @Environment(.presentationMode) var presentationMode @EnvironmentObject var movieStore: MovieStore var body: some View { NavigationView { VStack { SearchBar(text: $viewModel.searchText) List { ForEach(viewModel.tmdbMovies) { item in Data Flow - @StateObject
  • 58. struct DiscoverMoviesView: View { @StateObject var viewModel = DiscoverViewModel() @Environment(.presentationMode) var presentationMode @EnvironmentObject var movieStore: MovieStore var body: some View { NavigationView { VStack { SearchBar(text: $viewModel.searchText) List { ForEach(viewModel.tmdbMovies) { item in Data Flow - @StateObject Use for viewmodels
  • 59. struct DiscoverMoviesView: View { @EnvironmentObject var movieStore: MovieStore func addMovie(movie: TMDBMovie) { print("Adding (movie.title)") let newMovie = Movie(from: movie) movieStore.addMovie(newMovie) dismiss() } } Data Flow - @EnvironmentObject
  • 60. struct DiscoverMoviesView: View { @EnvironmentObject var movieStore: MovieStore func addMovie(movie: TMDBMovie) { print("Adding (movie.title)") let newMovie = Movie(from: movie) movieStore.addMovie(newMovie) dismiss() } } Data Flow - @EnvironmentObject Use for passingstuff down
  • 61. Se tt ing up Firebase for Swi ft UI 2
  • 62. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Sett ing up Firebase for Swi ft UI 2 😱 No more AppDelegate
  • 63. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Sett ing up Firebase for Swi ft UI 2 Let’s use theinitialiser
  • 64. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Sett ing up Firebase for Swi ft UI 2