加载所有喜欢帖子的用户

时间:2017-05-08 22:55:33

标签: ios json swift firebase firebase-realtime-database

我正在重建Instagram并希望向所有喜欢帖子的用户展示。 我遇到的问题是我的tableview没有显示喜欢该帖子的用户。

对于喜欢,我会将它添加到firebase

                    self.REF_LIKES_POSTS.child(postId).child(uid).setValue(true)

现在我想让所有喜欢我的UsersLikedViewController中的帖子的用户

  func loadUserLikes() {

    API.User.REF_POST_USERS_LIKED.observe(.childAdded, with: {
        snapshot in

        API.User.observeUserLikes(withPostId: snapshot.key, completion: {
            user in
            self.fetchUser(uid: user.id!, completed: {
                self.users.insert(user, at: 0)

                self.tableView.reloadData()
            })
        })
    })

}


func fetchUser(uid: String, completed: @escaping () -> Void) {

    API.User.observeUser(withId: uid, completion: {
        user in
        self.users.insert(user, at: 0)
        completed()
    })

}

我的用户API

class UserApi {

var REF_USERS = FIRDatabase.database().reference().child("users")
var REF_POST_USERS_LIKED = FIRDatabase.database().reference().child("LikesFromUsers")
var REF_POST = FIRDatabase.database().reference().child("posts")


func observeUser(withId uid: String,  completion: @escaping (User) -> Void) {

    REF_USERS.child(uid).observeSingleEvent(of: .value, with: {
        snapshot in
        if let dict = snapshot.value as? [String: Any] {
            let user = User.transformUserInfo(dict: dict, key: snapshot.key)
            completion(user)
        }
    })
}



func observeUsers(completion: @escaping (User) -> Void) {
    REF_USERS.observe(.childAdded, with: {
        snapshot in
        if let dict = snapshot.value as? [String: Any] {
            let user = User.transformUserInfo(dict: dict, key: snapshot.key)
            if user.id! != API.User.CURRENT_USER?.uid {
                completion(user)

            }
        }

    })
}


func observeUserLikes(withPostId id: String , completion: @escaping (User) -> Void) {
    REF_POST_USERS_LIKED.child(id).observeSingleEvent(of: .value, with: {
        snapshot in
        if let dict = snapshot.value as? [String: Any]{
            let allUsers = User.transformUserInfo(dict: dict, key: snapshot.key)
            completion(allUsers)
        }
    })
}

}

我在LoadUserLikes中的函数fetchUser()返回nil,所以缺少一些东西。 我只完成了所有已经共享的帖子,所以用户可以关注和取消关注帖子,但这没有任何意义哈哈。

感谢您的时间

 "LikesFromUsers" : {
"-KjY30xwWA2IJBwlvyzf" : {
  "jlkRoaucY6Q4GBkzhor5yAAl97I2" : true
}
  },
  "comments" : {
"-KjTIBDeMsho70t-jnGw" : {
  "commentText" : "klasse Auto",
  "creationDate" : 1.494083221667957E9,
  "likeCount" : 0,
  "uid" : "jlkRoaucY6Q4GBkzhor5yAAl97I2"
},
"-Kjc-uvCSn7qz8VkDVCR" : {
  "commentText" : "toll",
  "creationDate" : 1.494246203366448E9,
  "likeCount" : 0,
  "uid" : "es5fIbnKFpX4szcCbroUqHjJg6E3"
},
"-Kjc01pbWUtZn8XMlRGL" : {
  "commentText" : "fantatsico ",
  "creationDate" : 1.494246235776034E9,
  "likeCount" : 1,
  "likes" : {
    "es5fIbnKFpX4szcCbroUqHjJg6E3" : true
  },
   }
  },

"posts" : {
"-KjTBFFE5QzktG1IT5u0" : {
  "bookmarkCount" : 0,
  "caption" : "Toll",
  "commentCount" : 1,
  "creationDate" : 1.494081403379004E9,
  "hoursSinceUpload" : 0,
  "likeCount" : 0,
  "photoUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/Posts%2F76192CBE-55F0-4907-889A-849E196D5796?alt=media&token=de675609-4b73-411d-b402-f1ff3db64f79",
  "ratio" : 1.502732240437158,
  "score" : 16.38698994684219,
  "uid" : "jlkRoaucY6Q4GBkzhor5yAAl97I2"
},
"-KjTHFNe1RRS8Ly6bKsA" : {
  "bookmarkCount" : 1,
  "bookmarks" : {
    "jlkRoaucY6Q4GBkzhor5yAAl97I2" : true
  },
  "caption" : "Traumhaft",
  "commentCount" : 0,
  "creationDate" : 1.494082976550228E9,
  "hoursSinceUpload" : 0,
  "likeCount" : 2,
  "likes" : {
    "es5fIbnKFpX4szcCbroUqHjJg6E3" : true,
    "jlkRoaucY6Q4GBkzhor5yAAl97I2" : true
  },
  "photoUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/Posts%2F306BF7E1-9FEF-493A-ABF8-C0E061E8648F?alt=media&token=128bdd90-023a-49ac-8361-19c02c631183",
  "ratio" : 1.502732240437158,
  "score" : 166.6491847103437,
  "uid" : "jlkRoaucY6Q4GBkzhor5yAAl97I2"
},
"-KjY30xwWA2IJBwlvyzf" : {
  "bookmarkCount" : 1,
  "bookmarks" : {
    "jlkRoaucY6Q4GBkzhor5yAAl97I2" : true
  },
  "caption" : "Traumwagen",
  "commentCount" : 2,
  "creationDate" : 1.494163133228368E9,
  "hoursSinceUpload" : 0,
  "likeCount" : 2,
  "likes" : {
    "es5fIbnKFpX4szcCbroUqHjJg6E3" : true,
    "jlkRoaucY6Q4GBkzhor5yAAl97I2" : true
  },
  "photoUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/Posts%2F5C83FB24-BE21-49D9-863F-039FDE34969E?alt=media&token=e7e053a0-1966-4614-afad-42cab87f7880",
  "ratio" : 1.775,
  "score" : 280.0086305441856,
  "uid" : "jlkRoaucY6Q4GBkzhor5yAAl97I2",
  "videoUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/Posts%2F5951720B-54F4-44C1-859C-43D8ACB98334?alt=media&token=02be7eaf-4970-4059-b07d-036a4f182b28"
    }
  },


 "users" : {
"es5fIbnKFpX4szcCbroUqHjJg6E3" : {
  "email" : "user3@mail.de",
  "profilText" : "Schreib etwas über dich",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/profile_image%2Fes5fIbnKFpX4szcCbroUqHjJg6E3?alt=media&token=ce8d8722-39bc-457a-8149-e51c837ef0a3",
  "username" : "Blondine",
  "username_lowercase" : "blondine"
},
"jlkRoaucY6Q4GBkzhor5yAAl97I2" : {
  "email" : "user2@mail.de",
  "profilText" : "Schreib etwas über dich",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/profile_image%2FjlkRoaucY6Q4GBkzhor5yAAl97I2?alt=media&token=197ee89d-c328-4d04-a56e-02a9450b1720",
  "username" : "Marie",
  "username_lowercase" : "marie"
},
"tH3714ywXTOgGK0cxBgGvTiSDLl2" : {
  "email" : "user1@mail.de",
  "profilText" : "Schreib etwas über dich",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/funcloud-8e84e.appspot.com/o/profile_image%2FtH3714ywXTOgGK0cxBgGvTiSDLl2?alt=media&token=b08060a8-ef6b-4cf7-a73f-5bacd1ddada5",
  "username" : "Elena",
  "username_lowercase" : "elena"
}
  }
}

编辑:更多代码

 class HomeViewController: UIViewController {

@IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!
@IBOutlet weak var tableView: UITableView!
var posts = [Post]()
var users = [User]()

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.estimatedRowHeight = 521
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.dataSource = self
    loadPost()



    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
    tableView?.refreshControl = refreshControl




}

func handleRefresh() {
   posts.removeAll()

    loadPost()
  tableView.reloadData()
   self.tableView?.refreshControl?.endRefreshing()

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "CommentSegue" {
        let commentVC = segue.destination as! CommentViewController
        let postId = sender as! String
        commentVC.postId = postId
    }

    if segue.identifier == "Home_ProfileSegue" {
        let profileVC = segue.destination as! ProfileUserViewController
        let userId = sender as! String
        profileVC.userId = userId
    }

    if segue.identifier == "Home_Hashtag" {
        let hashTagVc = segue.destination as! HashTagViewController
        let tag = sender as! String
        hashTagVc.tag = tag
    }
}



func loadPost() {

    API.Feed.observeFeed(withId: API.User.CURRENT_USER!.uid) { (post) in
        guard let postUid = post.userId else {
            return
        }
        self.fetchUser(uid: postUid, completed: {


            self.posts.insert(post, at: 0)
            self.tableView.reloadData()
        })
        API.Post.calculateScore(postId: post.id!, onSuccess: { (post) in


        }) { (errorMessage) in
            ProgressHUD.showError(errorMessage)
        }

    }



    API.Feed.observeFeedRemoved(withId: API.User.CURRENT_USER!.uid) { (post) in

        self.posts = self.posts.filter{ $0.id != post.id }
        self.users = self.users.filter{$0.id != post.userId }

        self.tableView.reloadData()

    }
}
func fetchUser(uid: String, completed: @escaping () -> Void) {
    API.User.observeUser(withId: uid, completion: {
        user in

        self.users.insert(user, at: 0)
        completed()
    })

}
}



 extension HomeViewController: UITableViewDataSource {



func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! HomeTableViewCell


    let post = posts[indexPath.row]
    let user = users[indexPath.row]
    cell.post = post
    cell.user = user
    cell.delegate = self
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return posts.count
}

}

extension HomeViewController : HomeTableViewCellDelegate {
func goToCommentViewController(postId:String) {
    performSegue(withIdentifier: "CommentSegue", sender: postId)
}
func goToProfileUserViewController(userId: String) {
    performSegue(withIdentifier: "Home_ProfileSegue", sender: userId)
}

func goToHashtag(tag: String) {
    performSegue(withIdentifier: "Home_Hashtag", sender: tag)
}
func goToLikesViewController(postId:String) {
    performSegue(withIdentifier: "LikeSegue", sender: postId)
}

}

那个VC就像Instagram上的Feed,其中所有单元格都用于每个帖子。每个帖子都会计算喜欢它的用户,我希望向喜欢观察帖子的用户展示喜欢的内容,而不是硬编码的帖子。

谢谢。 :)

1 个答案:

答案 0 :(得分:0)

这就是我想出的。我使用你的JSON测试它,它工作。它可能与您的原始代码略有不同,但它应该让您了解如何实现它。此外,fetchUser函数似乎没用,所以我把它遗漏了,而username_lowercase是没有意义的,因为你可以在任何String上调用.lowercased()。

import UIKit
import Firebase

class LikesViewController: UITableViewController {

    var postId: String! // add this var

    var users = Array<User>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.loadUserLikes()
    }

    func loadUserLikes(){

        let api = UserApi()

        // changed this to var postId
        api.observeUserLikes(withPostId: postId) { (uids) in

            for uid in uids {

                api.observeUser(withId: uid, completion: { (user) in

                    if let currentUser = FIRAuth.auth()?.currentUser {

                        if uid == currentUser.uid {

                            self.users.insert(user, at: 0) // This will put the current user at the start of the array, so should be at top of table view.

                            self.tableView.reloadData()

                            return
                        }
                    }

                    self.users.append(user)

                    self.tableView.reloadData()
                })
            }
        }
    }

    // MARK: TableView Delegates
}

struct User {

    var uid: String

    var username: String

    var email: String

    var profileText: String

    var profileImageURL: String

    init?(uid: String, dict: Dictionary<String,String>) {

        guard

            let username = dict["username"],

            let email = dict["email"],

            let profileText = dict["profilText"],

            let profileImageURL = dict["profileImageUrl"]

        else {

            return nil
        }

        self.uid = uid

        self.username = username

        self.email = email

        self.profileText = profileText

        self.profileImageURL = profileImageURL
    }
}

class UserApi {

    var REF_USERS = FIRDatabase.database().reference().child("users")

    var REF_POST_USERS_LIKED = FIRDatabase.database().reference().child("LikesFromUsers")

    var REF_POST = FIRDatabase.database().reference().child("posts")

    func observeUser(withId uid: String,  completion: @escaping (User) -> Void) {

        REF_USERS.child(uid).observeSingleEvent(of: .value, with: { snapshot in

            guard let dict = snapshot.value as? Dictionary<String,String> else { return }

            if let user = User(uid: snapshot.key, dict: dict) {

                completion(user)

            } else {

                print("Incomplete User Data.")
            }
        })
    }

    func observeUsers(completion: @escaping (Array<User>) -> Void) {

        REF_USERS.observe(.value, with: { snapshot in

            guard let dict = snapshot.value as? Dictionary<String,Dictionary<String,String>> else { return }

            var users = Array<User>()

            for (key, value) in dict {

                if let user = User(uid: key, dict: value) {

                    guard let currentUser = FIRAuth.auth()?.currentUser else { return }

                    if user.uid != currentUser.uid {

                        users.append(user)
                    }

                } else {

                    print("Incomplete User Data.")
                }
            }

            completion(users)
        })
    }

    func observeUserLikes(withPostId id: String , completion: @escaping (Array<String>) -> Void) {

        REF_POST_USERS_LIKED.child(id).observeSingleEvent(of: .value, with: { snapshot in

            guard let dict = snapshot.value as? Dictionary<String,Bool> else { return }

            var users = Array<String>() // Array of user ids who liked the post.

            for (key, value) in dict {

                if value == true {

                    users.append(key)
                }
            }

            completion(users)
        })
    }

    // I've added this to get all the posts.
    func observePosts(completion: @escaping (Array<Post>) -> Void) {

        REF_POST.observe(.value, with: { snapshot in

            guard let dict = snapshot.value as? Dictionary<String,Dictionary<String,Any>> else { return }

            var posts = Array<Post>()

            for (key, value) in dict {

                if let post = Post(uid: key, dict: value) {

                    posts.append(post)

                } else {

                    print("Incomplete Post Data.")
                }
            }

            completion(posts)
        })
    }
}

这是我为测试Likes View Controller而制作的Post View控制器。

struct Post {

    var uid: String

    var photoUrl: String

    var ratio: Double

    var score: Double

    var creationDate: Date

    init?(uid: String, dict: Dictionary<String,Any>) {

        guard

            let photoUrl = dict["photoUrl"] as? String,

            let ratio = dict["ratio"] as? Double,

            let score = dict["score"] as? Double,

            let creationDate = dict["creationDate"] as? TimeInterval

            else {

                return nil
        }


        self.uid = uid

        self.photoUrl = photoUrl

        self.ratio = ratio

        self.score = score

        self.creationDate = Date(timeIntervalSince1970: creationDate)
    }
}

struct Comment {

    var uid: String

    var user: User

    var comment: String
}

class PostsViewController: UITableViewController {

    var posts = Array<Post>()

    override func viewDidLoad() {
        super.viewDidLoad()

        let api = UserApi()

        api.observePosts { (posts) in

            self.posts = posts

            self.tableView.reloadData()
        }
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.posts.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        // Configure the cell...

        let post = self.posts[indexPath.row]

        cell.textLabel?.text = post.uid

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // Just for testing, I have it show the likes view controller when the cell is tapped. 
        // Although you will probably have this as a button, so just copy this code into the action.

        let post = posts[indexPath.row]

        guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "LikesViewController") as? LikesViewController else { return }

        vc.postId = post.uid

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

这些屏幕截图仅显示帖子或用户的uid,但您可以更改此屏幕以显示所有必需的数据。

This is the Posts View Controller

This is the Likes View Controller