如何重用UITableView

时间:2015-12-10 16:44:42

标签: ios swift uitableview cell

我有一个UITableView,其中每个单元格都有一个图像。每当我选择其中一个单元格时,我就会更改当前单元格的图像。但是当我滚动并且单元格或单元格离开时,单元格会被重新创建或者一些,并且再次出现默认图像。我希望更改的图像保留在单元格上,直到视图卸载或消失。

以下是我UITableView的代表。

//UITableview delegate
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Arecipe.IngredientArr.count
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if(tableView == IngrediensTableView || tableView == ProcedureTableView)
    {
        print("Cell")

        let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
        let ingredient = self.Arecipe.IngredientArr[indexPath.row]

        cell.textLabel?.text = ingredient.UnitValue + " " + ingredient.UnitName + " " + ingredient.Name
        cell.imageView?.image = UIImage(named: "Ingr_Uncheck")
        cell.selectionStyle = .None

        return cell
    }

    return UITableViewCell()
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    print("Row \(indexPath.row) selected")

    if(tableView == IngrediensTableView || tableView == ProcedureTableView)
    {
        let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!

        if(cell.imageView?.image == UIImage(named: "Ingr_Uncheck"))
        {
            cell.imageView?.image = UIImage(named: "Ingr_Check")
        }
        else
        {
            cell.imageView?.image = UIImage(named: "Ingr_Uncheck")
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您在此处看到的是视图回收。这允许UITableView快速并使用更少的内存。

你应该保持'检查'状态逻辑与细胞分离。

在您的类中添加一个属性,用于存储已选中的IndexPath

var checkedIndexPath:NSIndexPath?

然后将选定的索引保存在checkedIndexPath

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let previousChecked = checkedIndexPath
    checkedIndexPath = indexPath    
    tableView.reloadRowsAtIndexPaths([previousChecked, checkedIndexPath], withRowAnimation:.Automatic)
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
    if indexPath == checkedIndexPath {
        cell.imageView?.image = UIImage(named: "Ingr_Check")        
    }
    else {
        cell.imageView?.image = UIImage(named: "Ingr_Uncheck")  
    }
}

答案 1 :(得分:0)

要启用单元重用(并提高内存消耗和性能),请更改以下行:

let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")

要:

let cell = tableView.dequeueReusableCellWithIdentifier("Cell")
        ?? UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")

并刷新单元格重用的选择状态,更改此行:

cell.imageView?.image = UIImage(named: "Ingr_Uncheck")

到此:

let selected = (tableView.indexPathsForSelectedRows ?? []).contains(indexPath)
cell.imageView?.image = UIImage(named: selected ? "Ingr_Check" : "Ingr_Uncheck")

这样您就可以重复使用看不见的单元格,并根据单元格的选择状态刷新图像。

我建议您继承UITableViewCell并移动图像选择'逻辑到单元格的setSelected方法。像这样:

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    imageView?.image = UIImage(named: selected ? "Ingr_Check" : "Ingr_Uncheck")
}

这样视图控制器代码会更清晰。在重用之前,您可以覆盖单元格中的prepareForReuse方法以重置为默认状态。要检查选择了哪些单元格,可以使用tableView.indexPathsForSelectedRows获取所选索引的列表。