SlideShare a Scribd company logo
1 of 64
Download to read offline
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

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
 
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 MorphiaMongoDB
 
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 SwiftChris 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 2012Amazon Web Services
 
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 JetpackAhmad Arif Faizin
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldChristian 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 StoryKon 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
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegapyangdj
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaveryangdj
 
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 FirebasePeter Friese
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsPeter Friese
 
CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara CloudStack Meetup Santa Clara
CloudStack Meetup Santa Clara NetApp
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick 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
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegap
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver
 
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 WorkshopPeter Friese
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsPeter Friese
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesPeter 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 LeedsPeter Friese
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in SwiftPeter Friese
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple DevelopersPeter 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 FirebasePeter 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 AuthPeter 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 AuthPeter 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 AssistantPeter 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 GooglePeter 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.0Peter Friese
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinPeter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android WearPeter Friese
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services RockPeter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android WearPeter 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 AndroidPeter 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-InPeter 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 RobolectricPeter 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

%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...masabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durbanmasabamasaba
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburgmasabamasaba
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationShrmpro
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 

Recently uploaded (20)

%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 

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