在 Swift 中显示所有使用 Firebase 的帖子?

Displaying all posts using Firebase in Swift?

我的目标是当用户打开该应用程序时,他们将看到该应用程序的每个用户的每个 post。我的数据树如下:

- posts 
    - UID
        - postKey
           --attributes 
- users 
    - UID 
       - attributes 

这是一个例子:

-posts
   -74anqEXU8kQHVr7IKoO3N9NNqDh1
     -MLzvs5VvXB_z7fhbh2p
        created_at: 1605242945.969368
        image_height: 414.6865671641791
        image_url: "https://firebasestorage...."
     -MLzvun01fNXNRbn7TPv
     -MM7zGyZ7GbenhlisJUZ
   -VGxqdzc2CkWWn39pa8xUofEWgNm2
   -pNvGg84JR0TbXvS4XlX8KbfBasz2
-users
   -74anqEXU8kQHVr7IKoO3N9NNqDh1
   -VGxqdzc2CkWWn39pa8xUofEWgNm2

我知道我必须对所有post做一个快照,然后显示在主控制器(SearchViewController)的viewDidLoad()中。我不知道如何显示所有 posts。

此代码用于显示当前用户的 posts,存储在名为 UserService.swift:

的文件中
static func posts(for user: User, completion: @escaping ([Post]) -> Void) {
        
        let ref = Database.database().reference().child("posts").child(user.uid)
        
        ref.observeSingleEvent(of: .value, with: { (snapshot) in
            guard let snapshot = snapshot.children.allObjects as? [DataSnapshot] else {
                return completion([])
            }
            
            let dispatchGroup = DispatchGroup()
            
            let posts: [Post] = snapshot.reversed().compactMap {
                guard let post = Post(snapshot: [=13=]) else { return nil }
                
                dispatchGroup.enter()
                
                   SaveService.isPostSaved(post) { (isSaved) in
                    post.isSaved = isSaved
                    dispatchGroup.leave()
                }
                
                return post
            }
            
            dispatchGroup.notify(queue: .main, execute: {
                completion(posts)
            })
        })
    }

然后在 SearchViewController 的 ViewDidLoad() 中:

        UserService.posts(for: User.current) { (posts) in
            self.posts = posts
            self.tableView.reloadData()
        }

但是我如何为所有 post 执行此操作。当我尝试以下操作时,它不会让我指定一个随机用户:

let ref = Database.database().reference().child("posts").child(User)

知道我可以在“.child(User”框中放入什么来完成这项工作吗?或者如何创建 for 循环以正确迭代?

*编辑

这是有效的方法:


    static func allPosts(completion: @escaping ([Post]) -> Void) {
        let ref = Database.database().reference().child("posts")

        ref.observeSingleEvent(of: .value, with: { (snapshot) in
            var postsArray = [Post]()
            
            for userSnapshot in snapshot.children {
                guard let snapshot = (userSnapshot as AnyObject).children.allObjects as? [DataSnapshot] else {
                    return completion([])
                }

                let dispatchGroup = DispatchGroup()

                let posts: [Post] = snapshot.reversed().compactMap {
                    guard let post = Post(snapshot:  [=16=]) else { return nil }
                    
postsArray
                    postsArray.append(post)
                    
                    dispatchGroup.enter()

                    SaveService.isPostSaved(post) { (isSaved) in
                        post.isSaved = isSaved
                        dispatchGroup.leave()
                    }
                    
                    return post
                }
                dispatchGroup.notify(queue: .main, execute: {
                    completion(postsArray)
                })
            }
        })
    }

你可以在JSON中观察更高一级,然后在回调中添加一个额外的循环:

let ref = Database.database().reference().child("posts")

ref.observeSingleEvent(of: .value, with: { (snapshot) in
    for userSnapshot in snapshot.children {
        guard let snapshot = userSnapshot.children.allObjects as? [DataSnapshot] else {
            return completion([])
        }
    
        let dispatchGroup = DispatchGroup()
    
        let posts: [Post] = snapshot.reversed().compactMap {
            guard let post = Post(snapshot: [=10=]) else { return nil }
            
            dispatchGroup.enter()
        
               SaveService.isPostSaved(post) { (isSaved) in
                post.isSaved = isSaved
                dispatchGroup.leave()
            }
        
            return post
        }        
    }
    dispatchGroup.notify(queue: .main, execute: {
        completion(posts)
    })

})

我可能忽略了一些东西,但目标似乎是

when users open the app they will see every post from every user

如果是这样,有时越简单越好;加载所有帖子,遍历它们,为每个帖子创建 Post 对象,然后重新加载 tableview (?)

let postsRef = self.ref.child("posts") //self.ref points to my firebase
postsRef.observeSingleEvent(of: .value, with: { snapshot in
    let allPosts = snapshot.children.allObjects as! [DataSnapshot]
    for postSnap in allPosts {
        let aPost = Post(initWithSnapshot: postSnap)
        self.postsArrray.append(post) //
    }
    self.postTableView.reloadData()
}

这假设您的 Post class 有一个方便的 init 来从快照填充它的属性。如果是这样,请在其中将 isSaved 设置为 true,因为正在使用保存的数据调用便利 init。

如果您在应用程序启动或视图加载时调用它,则不需要回调和 dispatchQueues。