【问题标题】:Initialize object with Firestore data within a model使用模型中的 Firestore 数据初始化对象
【发布时间】:2018-01-10 18:44:50
【问题描述】:

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

我可以循环抛出帖子数组中的每个帖子,并从 Firestore 获取用户数据并将其分配给视图控制器中的帖子属性,但我正在寻找的是一个计算属性或惰性属性从 Firestore 中获取数据,并在 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 (此代码不起作用并返回“Unexpected non-void return value in void function”错误)

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")
            }
        }
    }
}

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

【问题讨论】:

  • 您在编译时遇到的错误告诉您您正在返回一个 void 函数中的值。您实际上是从闭包返回,而不是从动态 var getter 块返回。如果您删除返回调用,您将在 setUser 块中获得缺少的返回。

标签: ios swift firebase google-cloud-firestore


【解决方案1】:

您的第二个代码 sn-p 似乎走在了正确的轨道上。您可以考虑在 initPost 时触发 setUser 函数,因为此时您将获得有效的 authorId

您收到该错误的原因是因为您试图在您的setUser 函数中返回一个User,而您真正需要做的只是更新您的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 的工作。将它放在一个为处理数据库函数而构建的单独类中会更有意义。

【讨论】:

  • 我认为您应该将 var setUser 更改为 func 以使其正常工作,并返回 void。
  • @CMont 我实际上是想让setUser 成为一个函数。当我复制/粘贴原始帖子时,我只是没有给予足够的关注。感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
相关资源
最近更新 更多