I have a function that fetches a user from FireStore. At the moment the function manually deals with the data. I want to change this using Codable. I have tried many functions but I cannot seem to get it to work. I think the code that is required is quite simple and short & I’m just not understanding something.
Here is the fetchUser function that needs to change to one that doesn’t manually map the data:
let ref = Firestore.firestore()
func fetchUser(uid: String,completion: @escaping (UserModel) -> ()){
let db = Firestore.firestore()
@EnvironmentObject var sharedData: SharedDataModel
ref.collection("Users").document(uid).getDocument { (doc, err) in
guard let user = doc else{return}
let username = user.data()?["username"] as? String ?? "No Username"
let pic = user.data()?["imageurl"] as? String ?? "No image URL"
let bio = user.data()?["bio"] as? String ?? "No bio"
let uid = user.data()?["uid"] as? String ?? ""
let isVerified = user.data()?["isVerified"] as? Bool ?? false
DispatchQueue.main.async {
completion(UserModel(username: username, pic: pic, bio: bio, uid: uid, isVerified: isVerified))
}
}
}
How do I change this function to manually map the data using Codable?
I want to do this because I want to implement another variable to the user model. This variable is favouriteItems.
Here is my UserModel
import SwiftUI
import FirebaseFirestoreSwift
struct UserModel: Identifiable, Codable{
@DocumentID var id: String?
var username : String
var pic : String
var bio: String
var uid : String
var isVerified: Bool
var favouriteItems: [FavouriteItems]
Code for FavouriteItem:
import SwiftUI
import FirebaseFirestoreSwift
struct FavouriteItems: Identifiable, Codable {
@DocumentID var id: String?
var item: Item
}
Code for Item:
import SwiftUI
import FirebaseFirestoreSwift
import Firebase
struct Item: Identifiable, Codable {
@DocumentID var id: String?
var item_name: String
var item_type: String
var item_image: String
var item_details: String
var item_uid : String
var didFavourite: Bool? = false
var isFavourite: Bool = false
}
2
Answers
try this approach, is this what you have tried already?
Since I do not have your database, I cannot test this.
EDIT-1: given your new info.
I see what is going on here, you have
UserModel
and nested inside is an array ofFavouriteItems
, etc…But you did not tell us that your
FavouriteItems
(which shoud be singular) is in another part of the database.That is why all answers tried to point you to mapping the simple model
UserModel
that you showed us at first.To obtain your complete
UserModel
, you need to re-structure your database and your structs, so that you havea
handle
on the differentDocumentReference
. SoUserModel
has a field ofDocumentReference
type, that points to the set ofFavouriteItems
, and inFavouriteItems
a field withDocumentReference
that points to the associatedItem
.Have a look at my attempt to deal with nested documents, here: Nested Struct with Document Reference in Swift Firestore
Note that since I do not have any access to the database, I cannot test any answers, I can only guess.
Add extinsion
confirm to decodable
fetch user
Second Way
user init with constructor as dict
and fetch