无法让Firestore将快照文档转换为“照片”对象

时间:2019-09-29 03:41:21

标签: ios swift firebase google-cloud-firestore

我在使用Firestore将Firebase Realtime Database的<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>302 Found</title> </head><body> <h1>Found</h1> <p>The document has moved <a href="https://dlang.org/">here</a>.</p> </body></html> 方法迁移到getPhotos时遇到问题,但是由于某种原因无法将getPhotos1中的文档快照迁移到{{1 }}对象。

这是我使用Firebase实时数据库的getPhotos1方法:

Photos1

这是对象

getPhotos

这是我使用Firestore的static func getPhotos (completion: @escaping ([Photo]) -> Void) { //Getting a reference to the database let dbRef = Database.database().reference() //Make the db call dbRef.child("photos").observeSingleEvent(of: .value) { (snapshot) in //Declare an array to hold the photos var retrievedPhotos = [Photo]() //Get the list of snapshots let snapshots = snapshot.children.allObjects as? [DataSnapshot] if let snapshots = snapshots { //Loop through each snapshot and parse out the photos for snap in snapshots { //Try to create a photo from a snapshot let p = Photo(snapshot: snap) //If successful, then add it to our array if p != nil { retrievedPhotos.insert(p!, at: 0) } } } //After parsing the snapshots, call the completion closure completion(retrievedPhotos) } } 方法,不起作用

import Foundation
import RealmSwift
import FirebaseDatabase
import Firebase

class Photo: Object {

    @objc dynamic var photoId:String?
    @objc dynamic var byId:String?
    @objc dynamic var byUsername:String?
    @objc dynamic var date:String?
    @objc dynamic var url:String?
    @objc dynamic var postId:String?

    override static func primaryKey() -> String? {
        return "photoId"
    }

    override static func indexedProperties() -> [String] {
        return ["byUsername"]
    }

    convenience init?(snapshot:DataSnapshot){
        self.init ()

        //Photo data
        let photoData = snapshot.value as? [String:String]

        if let photoData = photoData {

            let photoId = snapshot.key
            let byId = photoData["byId"]
            let byUsername = photoData["byUsername"]
            let date = photoData["date"]
            let url = photoData["url"]
            let postId = photoData["postId"]

            guard byId != nil && byUsername != nil && date != nil && url != nil && postId != nil else {
                return nil
            }
            self.photoId = photoId
            self.byId = byId
            self.byUsername = byUsername
            self.date = date
            self.url = url
            self.postId = postId

        }
    }
}

这是对象

getPhotos1

编辑10/1: 更新了getPhoto1方法。

    static func getPhotos1 (completion: @escaping ([Photo1]) -> Void) {

    //Get a Firebase reference
    let db = Firestore.firestore()
    db.collection("posts").getDocuments() {snapshot, error  in

        //Declare an array to hold the photos
        var retrievedPhotos = [Photo1]()

        if error == nil && snapshot != nil {
            for document in snapshot!.documents {
                let p = Photo1(snapshot: document)
                print(p!)
                if p != nil {
                retrievedPhotos.insert(p!, at: 0)
                //print("retrievedPhotos: \(retrievedPhotos)")
                }
            }
        }
        //After parsing the snapshots, call the completion closure
        completion(retrievedPhotos)
    }
}

但是我遇到此错误:

class Photo1: Object {

@objc dynamic var photoId:String?
@objc dynamic var byId:String?
@objc dynamic var byUsername:String?
@objc dynamic var date:String?
@objc dynamic var url:String?
@objc dynamic var postId:String?

override static func primaryKey() -> String? {
    return "photoId"
}

override static func indexedProperties() -> [String] {
    return ["byUsername"]
}

convenience init?(snapshot:DocumentSnapshot){
    self.init ()

    //Photo data
    let photoData = snapshot.data() as? [String:String]

    if let photoData = photoData {

        let photoId = snapshot.documentID
        let byId = photoData["byId"]
        let byUsername = photoData["byUsername"]
        let date = photoData["date"]
        let url = photoData["url"]
        let postId = photoData["postId"]

        guard byId != nil && byUsername != nil && date != nil && url != nil && postId != nil else {
            return nil
        }
        self.photoId = photoId
        self.byId = byId
        self.byUsername = byUsername
        self.date = date
        self.url = url
        self.postId = postId

    }
}
}

感谢您的建议。

我尝试在此上搜索以前的线程,尽管有几个线程,但由于它们不是特定于Swift的,所以我无法弄清楚。

1 个答案:

答案 0 :(得分:0)

问题中的代码有很多问题;我认为可能会引起某些混乱的三个不同的API(Firebase RealTime数据库,Firestore和Realm)。

让我们直接用Firestore的答案追逐。此代码将读取Firestore集合中的文档,基于该数据创建PhotoClass对象,并将它们存储在数组中。假设结构是这样

photos //a collection
   photo_0 //a document
      byUserName: "Henry"
      byId: "uid_0"
   photo_1
      byUserName: "George"
      byId: "uid_1"

这里是PhotoClass-我默认将属性设置为空字符串而不是nils,以减少处理nil的需要。由于我们没有使用Realm,因此我也删除了Object定义,并将vars更改为Swift vars,而不是Realm(@objc dynamic)所需的ObjC vars

class PhotoClass {
    var photoId = ""
    var byId = ""
    var byUsername = ""
    //var date:String?
    //var url:String?
    //var postId:String?

    init(withDocumentSnapshot: DocumentSnapshot) {
        self.photoId = withDocumentSnapshot.documentID
        self.byUsername = withDocumentSnapshot.get("userName") as? String ?? "No User Name"
        self.byId = withDocumentSnapshot.get("byId") as? String ?? "No uid"
    }
}

请注意,如果读取属性为nil,我将默认值设置为已知字符串。这样,如果属性丢失或为零,则应用程序不会崩溃。如果要使用nil值,那很酷,但是必须通过在整个过程中安全地使用它们来保护代码。

然后是一个数组,用于存储照片

var photosArray = [PhotoClass]()

然后使用代码读取photos节点内的所有文档,创建PhotoClass对象并填充数组

func readAllPhotos() {
    let photosCollection = self.db.collection("photos")
    photosCollection.getDocuments(completion: { snapshot, err in
        if let err = err {
            print(err.localizedDescription)
            return
        }

        for doc in snapshot!.documents {
            let photo = PhotoClass(withDocumentSnapshot: doc)
            self.photosArray.append(photo)
        }
    })
}

同样,请注意,有适当的代码可以检查错误并在未找到节点或发生其他错误的情况下保护应用程序。