首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用prepareForReuse

如何使用prepareForReuse
EN

Stack Overflow用户
提问于 2021-02-26 00:57:16
回答 2查看 165关注 0票数 0

有人能教我如何使用prepareForReuse吗?我读了文档,但我不明白。我在tableView上遇到了一些奇怪的行为。在tableviewCell中,每行有8个collectionViewCell。除了最后一个和倒数第二个单元格之外,每个单元格都有文本,单元格7和8具有带有用于某些函数调用的图像的文本。

但每当我滚动并单击第一张图像时,它都会调用这两个函数。它应该只调用它的映射函数(第一个函数),对第二个图像也是如此。

代码语言:javascript
复制
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
    cell.parentVC = self
    cell.index = indexPath.row
    if let val = arrData[indexPath.row] as? String{
        cell.textFieldValue.text = val.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    if let val = arrData[indexPath.row] as? NSNumber{
        cell.textFieldValue.text = (val).stringValue.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    
    cell.textFieldValue.isEditable = false
    cell.layer.borderColor = UIColor.gray.cgColor
    cell.layer.borderWidth = 0.5
    cell.textFieldValue.alignTextVertically()
    
    
    if((indexPath.row == 6) || (indexPath.row == 7)){
        cell.editButton.visibility = .visible
        cell.editButton.heightAnchor.constraint(equalToConstant: 15.0).isActive = true
        cell.editButton.widthAnchor.constraint(equalToConstant: 15.0).isActive = true
        if(indexPath.row == 6){
            cell.editButton.setImage(UIImage(named: "pencil-edit-button.png"), for: .normal)
            cell.editButton.addTarget(self, action: #selector(onCLickEditButton), for: .touchUpInside)
        }else if(indexPath.row == 7){
            cell.textFieldValue.textContainer.maximumNumberOfLines = 2
            cell.textFieldValue.textContainer.lineBreakMode = NSLineBreakMode.byTruncatingTail;
            cell.textFieldValue.alignTextVertically()
            cell.editButton.setImage(UIImage(named: "information.png"), for: .normal)
            cell.editButton.addTarget(self, action: #selector(onClickInfoButton), for: .touchUpInside)
        }
    }
    else{
        cell.textFieldValue.textContainer.maximumNumberOfLines = 2
        cell.textFieldValue.textContainer.lineBreakMode = NSLineBreakMode.byCharWrapping;
        cell.editButton.visibility = .gone
        cell.editButton.heightAnchor.constraint(equalToConstant: 0).isActive = true
        cell.editButton.widthAnchor.constraint(equalToConstant: 0).isActive = true
    }
    return cell
}

//CollectionViewCell

代码语言:javascript
复制
class CollectionViewCell: UICollectionViewCell, UITextViewDelegate  {

@IBOutlet weak var textFieldValue: UITextView!
@IBOutlet weak var editButton: UIButton!
var parentVC = UITableViewCell()
var index = Int()


override func awakeFromNib() {
    super.awakeFromNib()
    textFieldValue.delegate = self
    
}

}

EN

回答 2

Stack Overflow用户

发布于 2021-02-26 02:54:08

问题是对“重用”的误解。

假设您的计算单元中有一个UIView (我们将其称为someView),您的cellForItemAt函数执行以下操作:

代码语言:javascript
复制
if indexPath.row == 0 {
    cell.someView.backgroundColor = .red
}

当单元格第一次出列到第0行时,视图的背景将被设置为红色。

现在我们滚动一个方法,这样单元格就是reused...someView的背景仍然是红色的。

所以,一般来说,人们会这样做:

代码语言:javascript
复制
if indexPath.row == 0 {
    cell.someView.backgroundColor = .red
} else {
    cell.someView.backgroundColor = .white
}

您的代码所发生的情况是,您没有设置按钮的属性 --您正在添加一个操作。

因此,每次重用单元格时,您都会添加另一个操作。

在分配新目标之前,您可以每次都使用.removeTarget(...)

不过,一种更好的方法是在单元类本身中添加.touchUpInside操作,并在cellForItemAt中使用委托/协议模式或闭包(更好)。

顺便说一句,每次重用单元格时,您还会反复向编辑按钮添加宽度和高度约束。由于您每次都添加相同的约束,因此您可能不会遇到问题……但是如果单元格被重用,比如说20次,你的按钮上将有20组宽/高约束。

票数 1
EN

Stack Overflow用户

发布于 2021-02-26 07:25:36

prepareForReuse应该仅用于将单元格状态重置为初始状态。

单元的重用总是这样进行的:

cellForRowAt中,

  1. prepareForReusetableView本身调用
  2. 单元配置方法

示例:我们得到了一个单元格,该单元格将被tableView中的两个单元格重用。tableViewCell包括标签和imageView。在这个例子中,我们认为我们根本没有使用prepareForReuse函数。

因此我们首先配置1号单元格:

代码语言:javascript
复制
label.text = "cell 1"

imageView.image = UIImage(named: "exampleImage")

您的TableView尝试重用1号单元格并创建2号单元格:

代码语言:javascript
复制
label.text = "cell 2"

“我们不为2号单元格设置imageView”

现在发生了什么?

2号单元格将标签中的文本更新为“2号单元格”,但显示了1号单元格的图像,因为该单元格刚刚被重用,而我们从未将imageView的图像删除。如果我们使用函数prepareForReuse并设置:

代码语言:javascript
复制
imageView.image = nil

我们将imageView的图像设置为初始状态。如果我们有一个3号单元格再次使用图像,第一个prepareForReuse被tableView调用,然后你在cellForRowAt函数中调用你的configure方法,图像就被干净地设置好了。

因此,总之,您应该将在计算单元的cellForRowAt函数中配置的所有内容设置回prepareForReuse函数中的初始状态,以确保干净地重用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66373006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档