SlideShare una empresa de Scribd logo
1 de 53
Descargar para leer sin conexión
Building SwiftUI Apps with
Firebase
Peter Friese, Developer Advocate, Google
@peterfriese
🎉 JewelCase app demo
🤯 SwiftUI concepts
😅 Live coding: implementing a list in SwiftUI
🚰 Data Flow & Source of Truth
🔥 Firebase & Firestore Overview
🚶 Walk-through: Fetching data in real time from Firestore
Agenda
Demo 1
JewelCase - A movie tracking app
SwiftUI
• A declarative way to build your UI
• Everything is a view
• Every SwiftUI view is a struct
• You build UIs by composing views
• Views are a function of their state
Better state management!
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
SwiftUI Views
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
SwiftUI Views
struct ContentView: View {

var body: some View {

Text("Hello, World!")

}

}
SwiftUI Views
Data Flow & Source of Truth
Source of Truth
Data Model
Source of Truth
Data ModelUser Interface
?
Source of Truth
Data ModelUser Interface
1: update model
2: trigger update
3: redraw UI
Data Flow
• Properties
• @State
• @Binding
• @ObservedObject
• @StateObject (✨ new in SwiftUI 2)
• @EnvironmentObject
• Sarah Reichelt: SwiftUI Data Flow
(bit.ly/SwiftUIDataFlow)
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 - Property
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 - Property
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
Demo 2
Building a List From Scratch
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
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!
Setting up Firebase for SwiftUI 2
import SwiftUI

import Firebase

@main

struct JewelCaseApp: App {

@StateObject var movieStore = MovieStore()



init() {

FirebaseApp.configure()

}



var body: some Scene {

WindowGroup {

ContentView()

.environmentObject(movieStore)

}

}

}

Setting up Firebase for SwiftUI 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)

}

}

}

Setting up Firebase for SwiftUI 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)

}

}

}

Setting up Firebase for SwiftUI 2
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
❤
Thanks! Peter Friese, Developer Advocate, Google
@peterfriese
https://peterfriese.dev
https://medium.com/@peterfriese
https://github.com/@peterfriese
https://medium.com/firebase-developers
https://stackoverflow.com/questions/tagged/swiftui+firebase
https://github.com/firebase/firebase-ios-sdk
The End.
Building SwiftUI Apps with Firebase

Más contenido relacionado

Más de Peter Friese

Do Androids Dream of Electric Sheep
Do Androids Dream of Electric SheepDo Androids Dream of Electric Sheep
Do Androids Dream of Electric Sheep
Peter Friese
 

Más de Peter Friese (20)

Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
 
6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase Auth6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase Auth
 
Five Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase AuthFive Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase Auth
 
Building High-Quality Apps for Google Assistant
Building High-Quality Apps for Google AssistantBuilding High-Quality Apps for Google Assistant
Building High-Quality Apps for Google Assistant
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on GoogleBuilding Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google
 
What's new in Android Wear 2.0
What's new in Android Wear 2.0What's new in Android Wear 2.0
What's new in Android Wear 2.0
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & Xamarin
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services Rock
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
 
Google+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and AndroidGoogle+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and Android
 
Cross-Platform Authentication with Google+ Sign-In
Cross-Platform Authentication with Google+ Sign-InCross-Platform Authentication with Google+ Sign-In
Cross-Platform Authentication with Google+ Sign-In
 
Bring Back the Fun to Testing Android Apps with Robolectric
Bring Back the Fun to Testing Android Apps with RobolectricBring Back the Fun to Testing Android Apps with Robolectric
Bring Back the Fun to Testing Android Apps with Robolectric
 
Do Androids Dream of Electric Sheep
Do Androids Dream of Electric SheepDo Androids Dream of Electric Sheep
Do Androids Dream of Electric Sheep
 
Java based Cross-Platform Mobile Development
Java based Cross-Platform Mobile DevelopmentJava based Cross-Platform Mobile Development
Java based Cross-Platform Mobile Development
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 Hour
 
RestKit - From Zero to Hero
RestKit - From Zero to HeroRestKit - From Zero to Hero
RestKit - From Zero to Hero
 
Fake it til you make it
Fake it til you make itFake it til you make it
Fake it til you make it
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Último (20)

TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 

Building SwiftUI Apps with Firebase

  • 1. Building SwiftUI Apps with Firebase Peter Friese, Developer Advocate, Google @peterfriese
  • 2. 🎉 JewelCase app demo 🤯 SwiftUI concepts 😅 Live coding: implementing a list in SwiftUI 🚰 Data Flow & Source of Truth 🔥 Firebase & Firestore Overview 🚶 Walk-through: Fetching data in real time from Firestore Agenda
  • 3. Demo 1 JewelCase - A movie tracking app
  • 4.
  • 5.
  • 6. SwiftUI • A declarative way to build your UI • Everything is a view • Every SwiftUI view is a struct • You build UIs by composing views • Views are a function of their state Better state management!
  • 7. struct ContentView: View { var body: some View { Text("Hello, World!") } } SwiftUI Views
  • 8. struct ContentView: View { var body: some View { Text("Hello, World!") } } SwiftUI Views
  • 9. struct ContentView: View { var body: some View { Text("Hello, World!") } } SwiftUI Views
  • 10. Data Flow & Source of Truth
  • 12. Source of Truth Data ModelUser Interface ?
  • 13. Source of Truth Data ModelUser Interface 1: update model 2: trigger update 3: redraw UI
  • 14. Data Flow • Properties • @State • @Binding • @ObservedObject • @StateObject (✨ new in SwiftUI 2) • @EnvironmentObject • Sarah Reichelt: SwiftUI Data Flow (bit.ly/SwiftUIDataFlow)
  • 15. Unsure which one to use?
  • 16. 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 - Property
  • 17. 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 - Property Use for data thatdoesn’t change
  • 18. 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
  • 19. 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
  • 20. 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
  • 21. 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
  • 22. 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
  • 23. 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
  • 24. 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
  • 25. Demo 2 Building a List From Scratch
  • 26.
  • 27.
  • 28.
  • 29. 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
  • 30.
  • 31.
  • 35. collection("restaurants"). where("city", " ==", "Cairo"). orderBy(“rating”, "desc").limit(10) Here ya go!
  • 36. Setting up Firebase for SwiftUI 2
  • 37. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Setting up Firebase for SwiftUI 2 😱 No more AppDelegate
  • 38. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Setting up Firebase for SwiftUI 2 Let’s use theinitialiser
  • 39. import SwiftUI import Firebase @main struct JewelCaseApp: App { @StateObject var movieStore = MovieStore() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { ContentView() .environmentObject(movieStore) } } } Setting up Firebase for SwiftUI 2
  • 40. Fetching Data from Firestore
  • 41. // 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
  • 42. // 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
  • 43. // 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
  • 44. // 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
  • 45. // 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
  • 46. // 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
  • 47. Saving Data to Firestore
  • 48. let db = Firestore.firestore() do { _ = try db.collection(“movies") .addDocument(from: movie) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 49. let db = Firestore.firestore() do { _ = try db.collection(“movies") .addDocument(from: movie) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 50.
  • 51. Thanks! Peter Friese, Developer Advocate, Google @peterfriese https://peterfriese.dev https://medium.com/@peterfriese https://github.com/@peterfriese https://medium.com/firebase-developers https://stackoverflow.com/questions/tagged/swiftui+firebase https://github.com/firebase/firebase-ios-sdk