Swift 4和Firebase附加所有带有用户名和个人资料图片错误的帖子

时间:2018-08-19 00:43:26

标签: swift firebase firebase-realtime-database

我遇到了问题,我可以将所有帖子添加到我的收藏夹视图中,但用户名和profileImage更改为当前登录用户的身份。有人可以帮我弄清楚如何设置为发布它的用户吗?

import UIKit
import Firebase

class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    var cellId = "cellId"

    var filteredPosts = [Post]()
    var posts = [Post]()

    override func viewDidLoad() {
        super.viewDidLoad()

         NotificationCenter.default.addObserver(self, selector: #selector(handleUpdateFeed), name: PostController.updateFeedNotificationName, object: nil)

        collectionView?.backgroundColor = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1)

        collectionView?.register(HomePostCell.self, forCellWithReuseIdentifier: cellId)

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

        setupNavigationItems()

        fetchPosts()
    }

    @objc func handleUpdateFeed() {
        handleRefresh()
    }

    fileprivate func fetchPosts() {
        guard let uid = FIRAuth.auth()?.currentUser?.uid else { return }

        FIRDatabase.fetchUserWithUID(uid: uid) { (user) in
            self.fetchPostsWithUser(user: user)
        }
    }


    fileprivate func fetchPostsWithUser(user: User) {

        let ref = FIRDatabase.database().reference().child("posts")
        ref.observe(.childAdded, with: { (snapshot) in

            guard let dictionaries = snapshot.value as? [String: Any]
                else { return }

            dictionaries.forEach({ (key, value) in

                guard let userDictionary = value as? [String: Any] else { return }

                var post = Post(user: user, dictionary: userDictionary)

                self.posts.append(post)
            })

            self.posts.sort(by: { (post1, post2) -> Bool in
                return post1.creationDate.compare(post2.creationDate) == .orderedDescending
            })

            self.collectionView?.reloadData()

        }) { (err) in
            print("Failed to fetch posts.",err)
        }
        }

    @objc func handleRefresh() {
        self.posts.removeAll()
        self.fetchPosts()
        DispatchQueue.global(qos: .background).async {
            self.collectionView?.reloadData()
            self.collectionView?.refreshControl?.endRefreshing()
        }
    }

    func setupNavigationItems() {
        navigationItem.title = "Events"
        navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "download").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleFilter))
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return posts.count
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: view.frame.width, height: 200)
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! HomePostCell

        cell.post = posts[indexPath.item]

        return cell
    }
    }
import UIKit

class HomePostCell: UICollectionViewCell {

    var post: Post? {
        didSet{

            usernameLabel.text = post?.user.username

            guard let profileImageUrl = post?.user.profileImageUrl else { return }

            userProfileImageView.loadImage(urlString: profileImageUrl)

            setupCaptionText()
            setupDateLabel()
        }
    }

    let userProfileImageView: CustomImageView = {
        let iv = CustomImageView()
        iv.clipsToBounds = true
        iv.contentMode = .scaleAspectFill
        return iv
    }()

    let usernameLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 14)
        return label
    }()
    let captionLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.backgroundColor = .white
        return label
    }()

    let dateLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 14)
        return label
    }()

    let optionsButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("•••", for: .normal)
        button.setTitleColor(UIColor.black, for: .normal)
        return button
    }()

    fileprivate func setupCaptionText() {
        guard let post = self.post else { return }

        let attributedText = NSMutableAttributedString(string: " \(post.caption)", attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)])

        captionLabel.attributedText = attributedText
    }

    fileprivate func setupDateLabel() {
    guard let post = self.post else { return }

        let timeAgoDisplay = post.creationDate.timeAgoDisplay()
        let attributedText = NSMutableAttributedString(string: timeAgoDisplay, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14), NSAttributedStringKey.foregroundColor: UIColor.gray])

        dateLabel.attributedText = attributedText
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(userProfileImageView)
        userProfileImageView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: nil, paddingTop: 8, paddingLeft: 8, paddingBottom: 5, paddingRight: 0, width: 40, height: 40)
        userProfileImageView.layer.cornerRadius = 40 / 2

        backgroundColor = .white

        addSubview(usernameLabel)
        usernameLabel.anchor(top: topAnchor, left: userProfileImageView.rightAnchor, bottom: nil, right: nil, paddingTop: 12, paddingLeft: 8, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

        addSubview(captionLabel)
        captionLabel.anchor(top: userProfileImageView.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 10, paddingLeft: 8, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

        addSubview(optionsButton)
        optionsButton.anchor(top: topAnchor, left: nil, bottom: nil, right: rightAnchor, paddingTop: 5, paddingLeft: 0, paddingBottom: 0, paddingRight: 10, width: 0, height: 0)

        addSubview(dateLabel)
        dateLabel.anchor(top: nil, left: leftAnchor, bottom: bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 8, paddingBottom: 5, paddingRight: 0, width: 0, height: 0)

    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

import Foundation

struct User {
    var uid: String
    let username: String
    let profileImageUrl: String

    init(uid: String, dictionary: [String: Any]) {
        self.uid = uid
        self.username = dictionary["usernames"] as? String ?? ""
        self.profileImageUrl = dictionary["profileImageUrl"]  as? String ?? ""
    }
}

import Foundation

struct Post {

    var id: String?

    let user: User
    let caption: String
    let creationDate: Date


    init(user: User, dictionary: [String: Any]) {
        self.user = user
        self.caption = dictionary["caption"] as? String ?? ""

        let secondsFrom1970 = dictionary["creationDate"] as? Double ?? 0
        self.creationDate = Date(timeIntervalSince1970: secondsFrom1970)
    }
}

1 个答案:

答案 0 :(得分:0)

此代码在这里:

 fileprivate func fetchPosts() {
    guard let uid = FIRAuth.auth()?.currentUser?.uid else { return }

    FIRDatabase.fetchUserWithUID(uid: uid) { (user) in
        self.fetchPostsWithUser(user: user)
    }
}

您基本上是根据currentUser?.uid而不是创建帖子的用户进行查询。您将其传递给fileprivate func fetchPostsWithUser(user: User),因此它将检索相同的登录用户。

实际上,它应该传递数据库中每条帖子存储的user.uid(除非您要提取currentUser的帖子并显示它们。

发布时的每个发布都需要存储用户uid并将其存储在数据库中。然后进行查询,以根据用户的uid获取这些帖子。就像在帖子中一样,将用户缓存在数组中。

已更新:

class Post {

var id           : String?
var title        : String?
var content      : String?
var userUid      : String? 

static func transformDataToPost (dictionary: [String : Any], key: String) -> Post {
    let post = Post()
    post.id        = key // this is the snapshot.key that you get
    post.userUid   = dictionary["userUid"] as? String
    post.title     = dictionary["title"] as? String
    post.content   = dictionary["content"] as? String
    return
} 

现在,在观察帖子以从Firebase取回数据时,我在另一个类中使用了结构化的结构,即,我有一个单独的PostApi类,其中我处理了所有{ {1}}的请求,而不是API本身,但是想法是相同的。

UIViewController

要发送数据到var REF_POSTS = Database.database().reference().child("posts") func observePost(withId id: String, completion: @escaping (Post) -> Void) { REF_POSTS.child(id).observeSingleEvent(of: .value, with: { snapshot in if let dictionary = snapshot.value as? [String : Any] { let post = Post.transformDataToPost(dictionary: dictionary, key: snapshot.key) completion(post) } }) } ,请按以下方式操作:

FirebaseDatabase