从Firebase检索后,图片在UITableView中随机移动

时间:2017-01-16 20:06:09

标签: ios swift firebase swift3 firebase-storage

正如我的标题所述,当我滚动浏览表格视图时,我的tableView中的图片会移动并且不会显示在正确的帖子上。在我停止滚动后,它们似乎又回到原位。

我一直试图从以下文章中理解:

new Firebase retrieve data and put on the tableview swift

retrieve image from Firebase storage to show on tableview swift

swift Firebase sort posts in tableview by date

但我无法弄清楚如何让图片更好地显示。 这就是我所拥有的:

    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
        }

    }

}

我之所以遇到困难,是因为我希望用户的用户名,姓名和个人资料图片能够在编辑信息时随时随地进行更改。这就是我根据帖子的用户uid检索用户信息的原因。

实施此更好的方法是什么?

1 个答案:

答案 0 :(得分:3)

您必须覆盖prepareForReuse中的PostWithImageTableViewCell功能。

示例

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

修改

由于重用问题已经解决,我建议使用以下缓存框架Kingfisher,以获得更方便的图像显示体验。

Kingfisher在UIImageView上有一个很好的扩展,会为你的缓存提供什么。

在这里你将如何使用它:

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

您只需设置为URL,唯一标识图像资源的内容,并且只下载一次。这是一个cheat sheet,如何使用它。