首页 > 解决方案 > 为什么当我滚动表格视图或集合视图时,集合视图单元格中的数据会发生变化?

问题描述

我正在尝试将集合视图嵌入到表格视图中。当页面被加载时,我将从数据库中逐个字段地检索数据,并在我从数据库中检索单个字段时重新加载数据。在重新加载表格视图时,我需要检查值,即“oneimage”,因此如果该值不为空,则应将其设置为集合视图单元格。问题是每当我滚动表格视图时,集合视图单元格中的数据都会被交换。这是下面的代码

import UIKit
import Firebase
import FirebaseFirestore
import FirebaseAuth
import SDWebImage

struct values {
 var quesvalue: String
 var answvalue: String
 var ImageUrl = [String]()
}


class QuestionsCell: UITableViewCell,UICollectionViewDelegate {

 @IBOutlet weak var collectionview: UICollectionView!
 @IBOutlet weak var card: UIView!
 @IBOutlet weak var question: UILabel!
 @IBOutlet weak var answer: UILabel!
 @IBOutlet weak var speakbutton: UIButton!
 @IBOutlet weak var collectionviewh: NSLayoutConstraint!
 var imageArray = [String] ()
 override func awakeFromNib() {
    super.awakeFromNib()
 }
 override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

 }
}

extension QuestionsCell {
 func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & 
  UICollectionViewDelegate>(dataSourceDelegate: D, forRow row: Int) {
    collectionview.delegate = dataSourceDelegate
    collectionview.dataSource = dataSourceDelegate
    print("collectionviee.tag",collectionview.tag,row)
    collectionview.tag = row
    collectionview.contentOffset = .zero // Stops collection view if it was scrolling.
 }
}
class CollectionViewCell: UICollectionViewCell{

 @IBOutlet weak var backcard: UIView!
 @IBOutlet weak var imageview: UIImageView!
 var task: URLSessionDataTask?
 override func awakeFromNib() {
    super.awakeFromNib()

 }
 override func prepareForReuse(){
    imageview.image = nil
 }
}
class ViewController: UIViewController ,UITableViewDelegate, 
UITableViewDataSource,UICollectionViewDataSource,UICollectionViewDelegate {
@IBOutlet weak var tableview: UITableView!
var JSONArray = [String:Any]()
var quesArray = [String]()
var ansArray = [String]()
var answer : String!
var imagesarray = [String]()
var open : [values] = []
var oneimage = [String]()
var storedOffsets = [Int: CGFloat]()
override func viewDidLoad() {
    super.viewDidLoad()

    tableview.dataSource = self
    tableview.delegate = self

    tableview.rowHeight=UITableView.automaticDimension
    tableview.estimatedRowHeight=150
    Firestore.firestore().collection("User").document("7ngPwZin2wg7j5JZtI0hKJO8uSA2").collection("Popop").document("7ngPwZin2wg7j5JZtI0hKJO8uSA2").collection("Answers").document("Earlyyears").getDocument() { (document, error) in
                        if let document = document, document.exists {
                            self.open.removeAll()
                            self.imagesarray.removeAll()
                            self.oneimage.removeAll()
                            if let b1 = document.data()!["Name"] as? [String: Any] {
                                print("1",b1)
                                if let firstName = b1["Answer"] as? String {
                                    print("firstName is",firstName)

                                    if firstName != "No answer recorded"{
                                        self.answer = firstName
                                        self.ansArray.append(firstName)
                                        if let imageurlarray = b1["ImageURL"] as? [String] {
                                            self.imagesarray = imageurlarray
                                            print("imageurl array in meaning feild is",imageurlarray)
                                            self.open.insert(values(quesvalue: self.quesArray[0],answvalue: self.answer,ImageUrl: self.imagesarray), at: 0)
                                            self.tableview.reloadData()
                                        }


                                     }
                                }


                            }
                            if let b2 = document.data()!["Meaning"] as? [String: Any] {
                                print("1")
                                if let firstName = b2["Answer"] as? String {
                                    print("firstName is",firstName)

                                    if firstName != "No answer recorded"{
                                        self.answer = firstName
                                        self.ansArray.append(firstName)
                                        if let imageurlarray = b2["ImageURL"] as? [String] {
                                            self.imagesarray = imageurlarray
                                            print("imageurl array in meaning feild is",imageurlarray)
                                            self.open.insert(values(quesvalue: self.quesArray[1],answvalue: self.answer,ImageUrl: self.imagesarray), at: 1)
                                            self.tableview.reloadData()
                                        }


                                    }

                                }

                            }


                        } else {
                                print("Document does not exist")
                            }
                        }

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("ansArry.count is",open.count)
    return open.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("entered into cellfor row at")
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! QuestionsCell
    print("quesrray,ansArray are",quesArray,ansArray,open)
    if open.count > indexPath.row{

        cell.question.text = open[indexPath.row].quesvalue
        cell.answer.text = open[indexPath.row].answvalue
        print("cell.ques.text",cell.question.text)


        oneimage = open[indexPath.row].ImageUrl
        print("onimage before checking",oneimage)
        if !oneimage.isEmpty{
            print("entered into oneimage not empty",oneimage)
            cell.collectionview.isHidden = false
            cell.collectionviewh.constant  = 160

   cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)


        }
        else{
            print("dont show collection view")
            cell.collectionview.isHidden = true
            cell.collectionviewh.constant  = 0
        }

    }
    else{
        print("<")
    }

    return cell
}


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    print("imagesarray.count is",oneimage.count)

        print("oneimage.count")
        return oneimage.count


}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell: CollectionViewCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as? CollectionViewCell)!

  if oneimage.count > indexPath.row{
        if oneimage != [""] {
            let image = oneimage[indexPath.row]
            print("oneimage is",image)
            print("entered into oneimage not empty")
            cell.imageview.sd_setImage(with: URL(string: image))
         }
       }

    return cell

}

这是我的输出的屏幕截图。

页面加载后可见下图 当我滚动集合视图或表格视图时,可以看到以下页面

标签: swift

解决方案


正如我在评论中提到的,这是因为可重用性。这意味着当一个单元格从底部/顶部出去时,同一个单元格(包含以前的设置)从顶部/底部进来。所以如果你设置了一些异步的东西,比如一个远程图像,它可能在不正确的单元格上可见。当您要在其上设置图像时,您应该确保选择正确的单元格。

例如你应该改变这个:

cell.imageview.sd_setImage(with: URL(string: image))

像这样:

(collectionView.cellForItem(at: indexPath) as? CollectionViewCell)?.imageview.sd_setImage(with: URL(string: image))

这将要求collectionView真正的单元格而不是重复使用的单元格。我不知道sd图书馆是如何工作的,但你可能想在completionHandler图书馆里这样做。

也许这篇文章可以帮助你。


推荐阅读