@@ -15,53 +15,98 @@ class MappingSimpleTypesViewModel: ObservableObject {
1515
1616 private var db = Firestore . firestore ( )
1717
18+ /// Use this to alteratively use async/await or callback-based implementations
19+ let useAsync = false
20+
1821 func fetchAndMap( ) {
19- fetchBook ( documentId: " hitchhiker " )
22+ if useAsync {
23+ Task {
24+ await fetchBookAsync ( documentId: " hitchhiker " )
25+ }
26+ }
27+ else {
28+ fetchBook ( documentId: " hitchhiker " )
29+ }
2030 }
2131
2232 func fetchAndMapNonExisting( ) {
23- fetchBook ( documentId: " does-not-exist " )
33+ if useAsync {
34+ Task {
35+ await fetchBookAsync ( documentId: " does-not-exist " )
36+ }
37+ }
38+ else {
39+ fetchBook ( documentId: " does-not-exist " )
40+ }
2441 }
2542
2643 func fetchAndTryMappingInvalidData( ) {
27- fetchBook ( documentId: " invalid-data " )
44+ if useAsync {
45+ Task {
46+ await fetchBookAsync ( documentId: " invalid-data " )
47+ }
48+ }
49+ else {
50+ fetchBook ( documentId: " invalid-data " )
51+ }
52+ }
53+
54+ /// Alternative implementation that shows how to use async/await to call `getDocument`
55+ /// This needs to be marked as @MainActor so that we can safely access the errorMessage
56+ /// published property when encountering an error.
57+ @MainActor
58+ private func fetchBookAsync( documentId: String ) async {
59+ let docRef = db. collection ( " books " ) . document ( documentId)
60+ do {
61+ self . book = try await docRef. getDocument ( as: Book . self)
62+ }
63+ catch {
64+ switch error {
65+ case DecodingError . typeMismatch( _, let context) :
66+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
67+ case DecodingError . valueNotFound( _, let context) :
68+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
69+ case DecodingError . keyNotFound( _, let context) :
70+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
71+ case DecodingError . dataCorrupted( let key) :
72+ self . errorMessage = " \( error. localizedDescription) : \( key) "
73+ default :
74+ self . errorMessage = " Error decoding document: \( error. localizedDescription) "
75+ }
76+ }
2877 }
2978
3079 private func fetchBook( documentId: String ) {
3180 let docRef = db. collection ( " books " ) . document ( documentId)
3281
33- docRef. getDocument { document, error in
34- if let error = error as NSError ? {
35- self . errorMessage = " Error getting document: \( error. localizedDescription) "
36- }
37- else {
38- let result = Result { try document? . data ( as: Book . self) }
39- switch result {
40- case . success( let book) :
41- if let book = book {
42- // A Book value was successfully initialized from the DocumentSnapshot.
43- self . book = book
44- self . errorMessage = nil
45- }
46- else {
47- // A nil value was successfully initialized from the DocumentSnapshot,
48- // or the DocumentSnapshot was nil.
49- self . errorMessage = " Document doesn't exist. "
50- }
51- case . failure( let error) :
52- // A Book value could not be initialized from the DocumentSnapshot.
53- switch error {
54- case DecodingError . typeMismatch( _, let context) :
55- self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
56- case DecodingError . valueNotFound( _, let context) :
57- self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
58- case DecodingError . keyNotFound( _, let context) :
59- self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
60- case DecodingError . dataCorrupted( let key) :
61- self . errorMessage = " \( error. localizedDescription) : \( key) "
62- default :
63- self . errorMessage = " Error decoding document: \( error. localizedDescription) "
64- }
82+ // If you expect that a document might *not exist*, use an optional type (Book?.self)
83+ // and then perform an `if let book = book` dance to handle this case.
84+ docRef. getDocument ( as: Book ? . self) { result in
85+ switch result {
86+ case . success( let book) :
87+ if let book = book {
88+ // A Book value was successfully initialized from the DocumentSnapshot.
89+ self . book = book
90+ self . errorMessage = nil
91+ }
92+ else {
93+ // A nil value was successfully initialized from the DocumentSnapshot,
94+ // or the DocumentSnapshot was nil.
95+ self . errorMessage = " Document doesn't exist. "
96+ }
97+ case . failure( let error) :
98+ // A Book value could not be initialized from the DocumentSnapshot.
99+ switch error {
100+ case DecodingError . typeMismatch( _, let context) :
101+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
102+ case DecodingError . valueNotFound( _, let context) :
103+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
104+ case DecodingError . keyNotFound( _, let context) :
105+ self . errorMessage = " \( error. localizedDescription) : \( context. debugDescription) "
106+ case DecodingError . dataCorrupted( let key) :
107+ self . errorMessage = " \( error. localizedDescription) : \( key) "
108+ default :
109+ self . errorMessage = " Error decoding document: \( error. localizedDescription) "
65110 }
66111 }
67112 }
0 commit comments