使用模型中的Firestore数据初始化对象

时间:2018-01-10 18:44:51

标签: ios swift firebase google-cloud-firestore

我正在寻找一种干净的方式来分配并从我的帖子对象中获取用户/作者。

我可以循环抛出posts数组中的每个Post并从Firestore获取用户数据并将其从viewcontroller中分配给post属性,但我正在寻找的就像计算属性或lazy属性从Poststore获取数据并在Post初始化时自动将其添加到对象中。

如果有可能,或者这是正确的方法,我就不会这样做,努力尝试不同的方法而不取得任何成功。

这是我目前的帖子模型 - Post.swift

struct Post {
    var author: User?
    let authorUID: String
    let content: String

    init(authorUID: String, content: String) {
        self.authorUID = authorUID
        self.content = content
    }

    var dictionary: [String:Any] {
        return [
            "authorUID": authorUID,
            "content": content
        ]
    }
}

在我的viewController中,我有一个由来自Firestore数据库的数据填充的帖子数组 - PostViewController.swift

func loadAllPosts() {
    database.collection("posts").getDocuments { (querySnapshot, error) in
        if let error = error {
            print("Error when loading uhuus: \(error.localizedDescription)")
        } else {
            self.posts = querySnapshot!.documents.flatMap({Post(dictionary: $0.data())})

            DispatchQueue.main.async {
                self.tableview.reloadData()
            }
        }
    }
}

这就是我想象的Post模型看起来的样子 - Post.swift (此代码不起作用,并在void函数中返回"意外的非void返回值"错误)

struct Post {

    private var database = Firestore.firestore()

    var author: User?
    let authorUID: String
    let content: String

    init(authorUID: String, content: String) {
        self.authorUID = authorUID
        self.content = content
    }

    var dictionary: [String:Any] {
        return [
            "authorUID": authorUID,
            "content": content
        ]
    }

    private var setUser: User {
        database.collection("users").document(authorUID).getDocument {     (document, error) in
            if let user = document.flatMap({ User(dictionary: $0.data()) })     {
                return user
            } else {
                print("Document does not exist")
            }
        }
    }
}

如果你没有解决方案但是现在这是不好的做法,那么我想知道为什么以及什么是最好的方法。

1 个答案:

答案 0 :(得分:0)

您似乎与第二个代码段在正确的轨道上。您可以考虑在setUser init时触发Post函数,因为这将是您拥有有效authorId的位置。

您收到该错误的原因是因为您试图在User函数中返回 setUser,当您真正需要做的只是更新您的特定user上的Post变量。

我建议更新如下:

struct Post {

    private var database = Firestore.firestore()

    var author: User?
    let authorUID: String
    let content: String

    init(authorUID: String, content: String) {
        self.authorUID = authorUID
        self.content = content
        //Immediately fetch the User object here
        self.setUser()
    }

    var dictionary: [String:Any] {
        return [
            "authorUID": authorUID,
            "content": content
        ]
    }

    private func setUser() {
        database.collection("users").document(authorUID).getDocument { (document, error) in
            if let user = document.flatMap({ User(dictionary: $0.data()) }) {
                //Set the user on this Post
                self.author = user
            } else {
                print("Document does not exist")
            }
        }
    }
}

在某种程度上不相关的说明中,您可能希望避免在每个Post对象中包含数据库引用。如果你继续按照这里的方式工作,它仍然可以工作,但跟踪这个并不是Post的工作。将它放在一个为处理数据库函数而构建的单独类中更有意义。