从 Firebase 检索到的图片在 UITableView 中随机移动

Bru*_*las 1 ios firebase swift swift3 firebase-storage

正如我的标题所述,我的 tableView 中的图片会四处移动,并且在滚动 table view 时没有显示在正确的帖子上。在我停止滚动后,它们似乎又回到了原位。

我一直试图从以下文章中弄明白:

新的 Firebase 检索数据并迅速放在 tableview 上

从 Firebase 存储中检索图像以显示在 tableview swift 上

swift Firebase 按日期对 tableview 中的帖子进行排序

但我不知道如何使图片显示得更好。这是我所拥有的:

    import UIKit
    import FirebaseAuth
    import FirebaseDatabase
    import FirebaseStorage

    class MainFeedTableViewController: UITableViewController {

        var posts = [Post]()

        let alert = AlertsViewController()

        var databaseRef: FIRDatabaseReference! {
            return FIRDatabase.database().reference()
        }

        var storageRef: FIRStorage! {
            return FIRStorage.storage()
        }

    override func viewDidLoad() {
        super.viewDidLoad()

        fetchPosts()

    }

    // populates the tableView with posts content in real time
    private func fetchPosts(){

        let postRefs = databaseRef.child("posts")

        postRefs.observe(.value) { (snapshot: FIRDataSnapshot) in
            var newPost = [Post]()

            for post in snapshot.children{
                let postObject = Post(snapshot: post as! FIRDataSnapshot)
                newPost.insert(postObject, at: 0)
            }

            self.posts = newPost
            self.tableView.reloadData()
        }

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let postsAtIndexPath = posts[indexPath.row]

        if postsAtIndexPath.postWithImage == true {

            let cell = tableView.dequeueReusableCell(withIdentifier: "postWithImage", for: indexPath) as! PostWithImageTableViewCell

            let postUser = postsAtIndexPath.uid

            let userRef = databaseRef.child("users/\(postUser!)")

            userRef.observe(.value, with: { (snapshot) in

                let user = User(snapshot: snapshot)

                DispatchQueue.main.async(execute: {
                    cell.userRealNameLabel.text = user.name
                    cell.usernameLabel.text = "@" + user.username
                    cell.postTextView.text = postsAtIndexPath.postText
                    cell.timeStampLabel.text = postsAtIndexPath.date
                })

                self.storageRef.reference(forURL: user.photoURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in

                    if error == nil{

                        DispatchQueue.main.async(execute: {
                            if let data = data{
                                cell.userProfilePicture.image = UIImage(data: data)
                            }
                        })

                    }
                    else{

                        print(error!.localizedDescription)
                    }
                })

                self.storageRef.reference(forURL: postsAtIndexPath.postPictureURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in

                    if error == nil{

                        DispatchQueue.main.async(execute: {
                            if let data = data{
                                cell.postImage.image = UIImage(data: data)

                            }
                        })

                    }
                    else{
                        self.alert.displayAlert(alertTitle: "Error", alertMessage: error!.localizedDescription, fromController: self)
                    }
                })

            }) { (error) in
                self.alert.displayAlert(alertTitle: "Error", alertMessage: error.localizedDescription, fromController: self)
            }

            return cell
        }
        else{

            let cell = tableView.dequeueReusableCell(withIdentifier: "postWithText", for: indexPath) as! PostTableViewCell

            let postUser = postsAtIndexPath.uid

            let userRef = databaseRef.child("users/\(postUser!)")

            userRef.observe(.value, with: { (snapshot) in

                let user = User(snapshot: snapshot)

                DispatchQueue.main.async(execute: {
                    cell.userRealNameLabel.text = user.name
                    cell.usernameLabel.text = "@" + user.username
                    cell.postTextView.text = postsAtIndexPath.postText
                    cell.timestampLabel.text = postsAtIndexPath.date

                })

                self.storageRef.reference(forURL: user.photoURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in

                    if error == nil{

                        DispatchQueue.main.async(execute: {
                            if let data = data{
                                cell.userProfilePicture.image = UIImage(data: data)
                            }
                        })

                    }
                    else{

                        print(error!.localizedDescription)
                    }
                })

            }) { (error) in
                self.alert.displayAlert(alertTitle: "Error", alertMessage: error.localizedDescription, fromController: self)
            }

            return cell
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

我遇到困难的原因是,我希望用户的用户名、姓名和个人资料图片在他们编辑信息时随处实时更改。这就是我根据帖子的用户 uid 检索用户信息的原因。

什么是实现这一点的更好方法?

dir*_*nee 5

你必须重写prepareForReuse的功能PostWithImageTableViewCell

例子

 override func prepareForReuse() {
        super.prepareForReuse()
        self.userProfilePicture.image = nil
        //reset the rest of the values on your `UITableViewCell` subclass
 }
Run Code Online (Sandbox Code Playgroud)

编辑

既然解决了复用问题,我想推荐以下缓存框架Kingfisher,为了更方便的图像显示体验。

Kingfisher 有一个很好的扩展UIImageView,可以为您的.

您将如何使用它:

let url = URL(string: "https://domain.com/image.jpg")!
imageView.kf.setImage(with: url)
Run Code Online (Sandbox Code Playgroud)

您只需设置 URL,什么将唯一标识图像资源,并且仅下载一次。这是一个备忘单,如何使用它。