Reputation: 63
I have a project in swift with Firestore for the database. My firestore dataset of a user looks like this. User details with an array that contains objects.
I have a function that gets the specifick user with all firestore data:
func fetchUser(){
db.collection("users").document(currentUser!.uid)
.getDocument { (snapshot, error ) in
do {
if let document = snapshot {
let id = document.documentID
let firstName = document.get("firstName") as? String ?? ""
let secondName = document.get("secondName") as? String ?? ""
let imageUrl = document.get("imageUrl") as? String ?? ""
let joinedDate = document.get("joinedDate") as? String ?? ""
let coins = document.get("coins") as? Int ?? 0
let challenges = document.get("activeChallenges") as? [Challenge] ?? []
let imageLink = URL(string: imageUrl)
let imageData = try? Data(contentsOf: imageLink!)
let image = UIImage(data: imageData!) as UIImage?
let arrayWithNoOptionals = document.get("activeChallenges").flatMap { $0 }
print("array without opt", arrayWithNoOptionals)
self.user = Account(id: id, firstName: firstName, secondName: secondName, email: "", password: "", profileImage: image ?? UIImage(), joinedDate: joinedDate, coins: coins, activeChallenges: challenges)
}
else {
print("Document does not exist")
}
}
catch {
fatalError()
}
}
}
This is what the user model looks like:
class Account {
var id: String?
var firstName: String?
var secondName: String?
var email: String?
var password: String?
var profileImage: UIImage?
var coins: Int?
var joinedDate: String?
var activeChallenges: [Challenge]?
init(id: String, firstName: String,secondName: String, email: String, password: String, profileImage: UIImage, joinedDate: String, coins: Int, activeChallenges: [Challenge]) {
self.id = id
self.firstName = firstName
self.secondName = secondName
self.email = email
self.password = password
self.profileImage = profileImage
self.joinedDate = joinedDate
self.coins = coins
self.activeChallenges = activeChallenges
}
init() {
}
}
The problem is I don't understand how to map the activeChallenges from firestore to the array of the model. When I try : let challenges = document.get("activeChallenges") as? [Challenge] ?? []
The print contains an empty array, but when i do: let arrayWithNoOptionals = document.get("activeChallenges").flatMap { $0 } print("array without opt", arrayWithNoOptionals)
This is the output of the flatmap: it returns an optional array
Upvotes: 0
Views: 405
Reputation: 233
System can not know that activeChallenges is array of Challenge object. So, you need to cast it to key-value type (Dictionary) first, then map it to Challenge object
let challengesDict = document.get("activeChallenges") as? [Dictionary<String: Any>] ?? [[:]]
let challenges = challengesDict.map { challengeDict in
let challenge = Challenge()
challenge.challengeId = challengeDict["challengeId"] as? String
...
return challenge
}
This is the same way that you cast snapshot(document) to Account object
Upvotes: 3