简体   繁体   English

UITableView 的单元格从好图像闪烁到错误图像并在滚动后修复

[英]UITableView's cell is flickering from good to wrong image and fix after scrolling

I'm trying to fill UITableView's Cell with datas from my firestore database.我正在尝试用我的 firestore 数据库中的数据填充 UITableView 的 Cell。

For some reasons, when i switch to the app's tab containing my tableview, i can see the good image for half a second and then it flickers to the one of the preceding cell.由于某些原因,当我切换到包含我的表格视图的应用程序选项卡时,我可以看到半秒钟的好图像,然后它闪烁到前面的单元格之一。

Then, if i scroll down and goes back up, the good image is back but if i scroll up and down to fast, wrong images get called again.然后,如果我向下滚动并返回,好的图像又回来了,但如果我向上和向下滚动到快速,错误的图像会再次被调用。

To retrieve my datas and populate the cells i do like this:要检索我的数据并填充单元格,我这样做:

In my class file在我的 class 文件中

Retrieve the "main items" (This one works just fine)检索“主要项目” (这一项工作得很好)

  • Main item's ID主要物品的ID
  • sub item 1's ID子项 1 的 ID
  • sub item 2's ID子项 2 的 ID

Retrieve the details of "the sub items"检索“子项”的详细信息

  • sub item's ID子项目的ID
  • sub item's IMG URL子项目的 IMG URL
  • ... ...

This code also include "useless" code used for testing purpose, in a hope of finding the solution..该代码还包括用于测试目的的“无用”代码,以期找到解决方案..

    var groupNom:String = ""
    var groupStyles:String = ""
    var groupHeaderImg = [StorageReference]()
    var groupIconeImg = [StorageReference]()
    var videosArrayed = [String]()
    var groupIconeURL:String = ""

    func getGroupDetails(Did: String, completion: @escaping (_ message: String) -> Void) {

        let db = Firestore.firestore()
        let storage = Storage.storage()

        let docRef = db.collection("groups").document(Did)

        docRef.getDocument { (document, error) in
            if let document = document, document.exists {

                self.groupNom = document.get("nom") as! String
                self.groupStyles = document.get("styles") as! String
                let icone_img = document.get("icone_img") as! String

                self.groupIconeImg.removeAll()
                self.groupIconeImg.append(storage.reference(forURL: self.StorageRefRoot + "/groups/" + document.documentID + "/icones/" + icone_img + ".png"))
                //self.groupIconeURL.removeAll()
                self.groupIconeURL = self.StorageRefRoot + "/groups/" + document.documentID + "/icones/" + icone_img + ".png"
                //print("id: \(Did) array d'icone: \(self.groupIconeImg)")
                self.groupHeaderImg.append(storage.reference(forURL:"\(self.StorageRefRoot)/groups/\(Did)/headers/\(document.get("header_img") as! String).png"))

                let stylesNSArray = document.get("styles_ids") as! Array<Any>
                let stylesArrayed: [String] = stylesNSArray.compactMap({ $0 as? String })


                var tempGroupStyles = ""


                for i in stylesArrayed.indices {

                    let styleDocRef = db.collection("styles_groupes").document(stylesArrayed[i])
                    styleDocRef.getDocument { (document, error) in
                        if let document = document, document.exists {
                            //tempBarStyles = ""
                            if i < stylesArrayed.count-1 { // Si c'est le dernier element, on n'ajoute pas de virgule
                                tempGroupStyles = "\(tempGroupStyles)\(document.get("nom") as! String), "
                            } else {
                                tempGroupStyles = "\(tempGroupStyles)\(document.get("nom") as! String)"
                                //print("barstyles = \(tempGroupStyles)")

                            }

                            if i == stylesArrayed.count-1 {
                                self.groupStyles = tempGroupStyles
                            }

                        } else {
                            print("style to be decrypted do not exist")
                            return
                        }
                        completion("done")
                    }
                }

                let videosNSArray = document.get("videos_yt_ids") as! Array<Any>
                self.videosArrayed = videosNSArray.compactMap({ $0 as? String })



            } else {
                print("Groups details does not exist")
                return
            }
            completion("done")
        }

    }

In my ViewController在我的视图控制器中

  • Return as many cells as there are Main items by running the Main items' class (This one works just fine)通过运行主要项目的 class 返回与主要项目一样多的单元格(这个工作得很好)
  • For each Main items, retrieve the details of the sub items' ID by running the sub items' class对于每个主要项目,通过运行子项目的 class 检索子项目 ID 的详细信息

This code also include "useless" code used for testing purpose, in a hope of finding the solution..该代码还包括用于测试目的的“无用”代码,以期找到解决方案..

    var feedAbos = abo()
    var feedBars = bar()
    var feedGroupes = group()

    @IBOutlet weak var abosCollectionView: UICollectionView!
    @IBOutlet weak var aboFeedTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()


    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated) // No need for semicolon

        if Auth.auth().currentUser != nil {
            //print("l'utilisateur en cours est: \(String(describing: Auth.auth().currentUser?.uid))")

            feedAbos = abo()
            feedAbos.getAbosFeed(uid: Auth.auth().currentUser!.uid, completion: { message in
                self.aboFeedTableView.reloadData()
            })
        } else {
            showLoginVC(viewToPresent: self, isModale: true)
        }



    }

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

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


        self.feedGroupes.getGroupDetails(Did: self.feedAbos.feedGroupesID[indexPath.row], completion: { message in
            if self.feedGroupes.groupIconeURL != "" {
                            cell.liveFeedGroupeImage.sd_setImage(with: URL(string: self.feedGroupes.groupIconeURL), placeholderImage: UIImage(named: "PLACEHOLDER1"))
            } else {
                cell.liveFeedGroupeImage.image = UIImage(named: "PLACEHOLDER1")
            }

            cell.liveFeedGroupeImage.layer.cornerRadius = 5
            cell.liveFeedGroupeNomLabel?.text = self.feedAbos.feedGroupesID[indexPath.row]

        })
        cell.liveFeedDateLabel?.text = self.feedAbos.feedLivesDates[indexPath.row]
        return cell
    }

class abosLivesFeedCell: UITableViewCell {

    @IBOutlet weak var liveFeedBarImage: UIImageView!
    @IBOutlet weak var liveFeedGroupeImage: UIImageView!
    @IBOutlet weak var liveFeedGroupeNomLabel: UILabel!
    @IBOutlet weak var liveFeedDateLabel: UILabel!
    @IBOutlet weak var liveFeedBarNomLabel: UILabel!

    override func prepareForReuse() {
        super.prepareForReuse()
        self.liveFeedGroupeImage.image = nil
    }
}

I think it has to do with the fact i use async data downloading.我认为这与我使用异步数据下载有关。 I'm thinking that maybe it has to do with the way i handle completion of my firestore classes... I also read about dispatching methods but i never used that yet.我在想,这可能与我处理完成 Firestore 类的方式有关……我还阅读了有关调度方法的信息,但我从未使用过。

I am pretty lost right know as it may just be something i don't know as i am definitely not a professional coder:)我很迷茫,因为这可能只是我不知道的事情,因为我绝对不是专业的编码员:)

Hope someone can point me in the right direction or show me where i did that stupid and very visible mistake;D希望有人能指出我正确的方向或告诉我我在哪里犯了那个愚蠢且非常明显的错误;D

Thank you everyone !谢谢大家 !

Ok, here is what i just did to make it work.好的,这就是我刚刚为使其工作所做的事情。 I don't think that it's the right way but it seems to work.. so..我不认为这是正确的方法,但它似乎工作......所以......

In my ViewController i check if the Sub item's ID from the Main items' class is the same as the one retrieved from the sub items' class.在我的 ViewController 中,我检查主项目 class 中的子项目 ID 是否与从子项目 class 中检索到的 ID 相同。 If so, i load the sub items' class image into my cell.如果是这样,我将子项目的 class 图像加载到我的单元格中。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView
            .dequeueReusableCell(withIdentifier: "abosLivesFeedCell", for: indexPath as IndexPath) as! abosLivesFeedCell
        cell.liveFeedGroupeImage.image = UIImage(named: "PLACEHOLDER1")

        self.feedGroupes.getGroupDetails(Did: self.feedAbos.feedGroupesID[indexPath.row], completion: { message in
            if self.feedGroupes.groupID == self.feedAbos.feedGroupesID[indexPath.row] {
                            cell.liveFeedGroupeImage.sd_setImage(with: URL(string: self.feedGroupes.groupIconeURL), placeholderImage: UIImage(named: "PLACEHOLDER1"))
            } else {

            }

            cell.liveFeedGroupeImage.layer.cornerRadius = 5
            cell.liveFeedGroupeNomLabel?.text = self.feedAbos.feedGroupesID[indexPath.row]

        })
        cell.liveFeedDateLabel?.text = self.feedAbos.feedLivesDates[indexPath.row]
        return cell
    }

Hopefully one day i'll find where i am wrong.希望有一天我能找到我错的地方。 if so, i'll update the answer!如果是这样,我会更新答案!

thanks everyone.感谢大家。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM