I've been trying to convert the document retrieved from the Firebase's Cloud Firestore to a custom object in Swift 5. I'm following the documentation:
However, Xcode shows me the error Value of type 'NSObject' has no member 'data'
for the line try $0.data(as: JStoreUser.self)
. I've defined the struct as Codable
.
The code:
func getJStoreUserFromDB() {
db = Firestore.firestore()
let user = Auth.auth().currentUser
db.collection("users").document((user?.email)!).getDocument() {
(document, error) in
let result = Result {
try document.flatMap {
try $0.data(as: JStoreUser.self)
}
}
}
}
The user struct:
public struct JStoreUser: Codable {
let fullName: String
let whatsApp: Bool
let phoneNumber: String
let email: String
let creationDate: Date?
}
The screenshot:
Does anyone know how to resolve this?
After contacting the firebase team, I found the solution I was looking for. It turns out I have to do import FirebaseFirestoreSwift
explicitly instead of just doing import Firebase
. The error will disappear after this. (And of course you'll need to add the pod to your podfile first:D)
You can do it as shown below:-
First create model class:-
import FirebaseFirestore
import Firebase
//#Mark:- Users model
struct CommentResponseModel {
var createdAt : Date?
var commentDescription : String?
var documentId : String?
var dictionary : [String:Any] {
return [
"createdAt": createdAt ?? "",
"commentDescription": commentDescription ?? ""
]
}
init(snapshot: QueryDocumentSnapshot) {
documentId = snapshot.documentID
var snapshotValue = snapshot.data()
createdAt = snapshotValue["createdAt"] as? Date
commentDescription = snapshotValue["commentDescription"] as? String
}
}
Then you can convert firestore document into custom object as shown below:-
func getJStoreUserFromDB() {
db = Firestore.firestore()
let user = Auth.auth().currentUser
db.collection("users").document((user?.email)!).getDocument() { (document, error) in
// Convert firestore document your custom object
let commentItem = CommentResponseModel(snapshot: document)
}
}
You need to initialize your struct and then you can extend the QueryDocumentSnapshot and QuerySnapshot like:
extension QueryDocumentSnapshot {
func toObject<T: Decodable>() throws -> T {
let jsonData = try JSONSerialization.data(withJSONObject: data(), options: [])
let object = try JSONDecoder().decode(T.self, from: jsonData)
return object
}
}
extension QuerySnapshot {
func toObject<T: Decodable>() throws -> [T] {
let objects: [T] = try documents.map({ try $0.toObject() })
return objects
}
}
Then, try to call the Firestore db by:
db.collection("users").document((user?.email)!).getDocument() { (document, error) in
guard error == nil else { return }
guard let commentItem: [CommentResponseModel] = try? document.toObject() else { return }
// then continue with your code
}
let jsonData = try JSONSerialization.data(withJSONObject: jsonObj, options: .prettyPrinted)
let jsonModel: Model = try JSONDecoder().decode(Model.self, from: jsonData)
In the past, I had some issues though importing FirebaseFirestore with the package manager in my project. So I explain about the access to FirebaseFirestore in swift.
SnapshotListener
import Foundation import FirebaseFirestore class BooksViewModel: ObservableObject { @Published var books = [Book]() private var db = Firestore.firestore() func fetchData() { db.collection("books").addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot?.documents else { print("No documents") return } self.books = documents.map { queryDocumentSnapshot -> Book in let data = queryDocumentSnapshot.data() let title = data["title"] as? String?? "" let author = data["author"] as? String?? "" let numberOfPages = data["pages"] as? Int?? 0 return Book(id:.init(), title: title, author: author, numberOfPages: numberOfPages) } } } }
using uid and getDocument function
Firestore.firestore().collection("users").document(uid).getDocument { snapshot, error in if let error = error { self.errorMessage = "Failed to fetch current user: \(error)" print("Failed to fetch current user:", error) return } guard let data = snapshot?.data() else { self.errorMessage = "No data found" return } let uid = data["uid"] as? String?? "" let email = data["email"] as? String?? "" let profileImageUrl = data["profileImageUrl"] as? String?? "" self.chatUser = ChatUser(uid: uid, email: email, profileImageUrl: profileImageUrl) }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.