Map array to be conform with a Model in MVVM structure Swift

Viewed 80

I fetch data from Firebase and in this data I have an array of dictionary.

I need to set this array of dictionary in days conform to StickModel because the key days in HabitModel need to be conform with [StickModel].

But I get this error :

Error

I use MVVM structure.

import Foundation
import Firebase

class HabitsViewModel: ObservableObject {
    @Published var habites = [HabitModel]()
    @Published var days = [StickModel]()
    
    private var db = Firestore.firestore()
    
    func fetchData() {
        debugPrint("Fetch Data...")
        db.collection("users/" + (Auth.auth().currentUser?.uid)! + "/Habits").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                debugPrint("No document")
                return
            }
            
            self.habites = documents.map { queryDocumentSnapshot -> HabitModel in
                let data = queryDocumentSnapshot.data()
                let id = queryDocumentSnapshot.documentID
                let title = data["title"] as? String ?? ""
                let progress = data["progress"] as? Float ?? 0
                let start = data["start"] as? String ?? ""
                let end = data["end"] as? String ?? ""
                
                                
                self.days = data["days"].map { myday -> StickModel in
                    
                    let completed = myday["completed"] as? Bool ?? false
                    let dayLetter = myday["day"] as? String ?? ""
                    let progress = myday["progress"] as? Float ?? 0
                    
                    return StickModel(id: UUID().uuidString, progress: progress, completed: completed, day: dayLetter)
                }
                
                
                return HabitModel(id: id, title: title, progress: progress, start: start, end: end, days: self.days)
            }
        }
    }
}
2 Answers

Firstore supports Codable, for mapping Firestore documents from/to Swift, which removes the need for manually mapping the individual fields, and makes the whole process much easier to write and less error-prone.

Here is how:

  1. Add FirebaseFirestoreSwift to your project. You can use either CocoaPods or the Swift Package Manager to do so.
  2. Import FirebaseFirestoreSwift
  3. Conform your type to Codable
  4. Add an id property to your type, and use @DocumentID to tell Firestore to map this to the document ID
  5. Use documentReference.data(as: ) to map a document reference to a Swift type
  6. Use documentReference.setData(from: ) to map data from Swift types to a Firestore document
  7. (optional, but highly recommended) Implement proper error handling

For more details, check out Mapping Firestore Data in Swift - The Comprehensive Guide

Try this:

self.days = (data["days"] as? [[String: Any]] ?? []).map -> StickModel in
Related