我正在重建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,其中所有单元格都用于每个帖子。每个帖子都会计算喜欢它的用户,我希望向喜欢观察帖子的用户展示喜欢的内容,而不是硬编码的帖子。
谢谢。 :)
答案 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,但您可以更改此屏幕以显示所有必需的数据。