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
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
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!
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

jQuery
jQueryjQuery
jQuery
Jay Poojara
 
Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...
Thinqloud
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
Marc Grabanski
 
Simplifying Persistence for Java and MongoDB with Morphia
Simplifying Persistence for Java and MongoDB with MorphiaSimplifying Persistence for Java and MongoDB with Morphia
Simplifying Persistence for Java and MongoDB with Morphia
MongoDB
 
Morphia: Simplifying Persistence for Java and MongoDB
Morphia:  Simplifying Persistence for Java and MongoDBMorphia:  Simplifying Persistence for Java and MongoDB
Morphia: Simplifying Persistence for Java and MongoDBJeff Yemin
 

What's hot (7)

jQuery
jQueryjQuery
jQuery
 
Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...Learning jQuery made exciting in an interactive session by one of our team me...
Learning jQuery made exciting in an interactive session by one of our team me...
 
Jquery
JqueryJquery
Jquery
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
 
Simplifying Persistence for Java and MongoDB with Morphia
Simplifying Persistence for Java and MongoDB with MorphiaSimplifying Persistence for Java and MongoDB with Morphia
Simplifying Persistence for Java and MongoDB with Morphia
 
Morphia: Simplifying Persistence for Java and MongoDB
Morphia:  Simplifying Persistence for Java and MongoDBMorphia:  Simplifying Persistence for Java and MongoDB
Morphia: Simplifying Persistence for Java and MongoDB
 
jQuery Presentasion
jQuery PresentasionjQuery Presentasion
jQuery Presentasion
 

Similar to Building Apps with SwiftUI and Firebase

Try!Swift India 2017: All you need is Swift
Try!Swift India 2017: All you need is SwiftTry!Swift India 2017: All you need is Swift
Try!Swift India 2017: All you need is Swift
Chris Bailey
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
Amazon Web Services
 
From newbie to ...
From newbie to ...From newbie to ...
From newbie to ...
Vitali Pekelis
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksmwbrooks
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
Ahmad Arif Faizin
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
Christian Melchior
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle Story
Kon Soulianidis
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WAREFermin Galan
 
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...Patrick Lauke
 
JavaScript APIs - The Web is the Platform - .toster conference, Moscow
JavaScript APIs - The Web is the Platform - .toster conference, MoscowJavaScript APIs - The Web is the Platform - .toster conference, Moscow
JavaScript APIs - The Web is the Platform - .toster conference, MoscowRobert Nyman
 
WebRTC & Firefox OS - presentation at Google
WebRTC & Firefox OS - presentation at GoogleWebRTC & Firefox OS - presentation at Google
WebRTC & Firefox OS - presentation at GoogleRobert Nyman
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaveryangdj
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegapyangdj
 
Storage Plug-ins
Storage Plug-ins Storage Plug-ins
Storage Plug-ins buildacloud
 
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
Peter Friese
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
Peter Friese
 
CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara
NetApp
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee
 

Similar to Building Apps with SwiftUI and Firebase (20)

Android workshop
Android workshopAndroid workshop
Android workshop
 
Try!Swift India 2017: All you need is Swift
Try!Swift India 2017: All you need is SwiftTry!Swift India 2017: All you need is Swift
Try!Swift India 2017: All you need is Swift
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
From newbie to ...
From newbie to ...From newbie to ...
From newbie to ...
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorks
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
Phactory
PhactoryPhactory
Phactory
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle Story
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WARE
 
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
 
JavaScript APIs - The Web is the Platform - .toster conference, Moscow
JavaScript APIs - The Web is the Platform - .toster conference, MoscowJavaScript APIs - The Web is the Platform - .toster conference, Moscow
JavaScript APIs - The Web is the Platform - .toster conference, Moscow
 
WebRTC & Firefox OS - presentation at Google
WebRTC & Firefox OS - presentation at GoogleWebRTC & Firefox OS - presentation at Google
WebRTC & Firefox OS - presentation at Google
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegap
 
Storage Plug-ins
Storage Plug-ins Storage Plug-ins
Storage Plug-ins
 
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
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
 
CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 

More from Peter Friese

Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI Workshop
Peter Friese
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
Peter Friese
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroes
Peter Friese
 
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
Peter Friese
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
Peter Friese
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple Developers
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & Xamarin
Peter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
Peter Friese
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services Rock
Peter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 
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
Peter Friese
 

More from Peter Friese (20)

Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI Workshop
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroes
 
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple Developers
 
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
 

Recently uploaded

Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 

Recently uploaded (20)

Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 

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
  • 4.
  • 5.
  • 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
  • 17.
  • 18.
  • 19.
  • 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
  • 21.
  • 22.
  • 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