我的TableView在滚动时重复使用了已选择的单元格 -- 使用SWIFT

7

早上好

我的问题是,当我向下滚动并再次向上滚动时,我的表视图重用了已选择的单元格。也就是说,当我从上面选择一个单元格然后向下滚动时,一些我没有选择的单元格会显示为已选择状态,而当我再次向上滚动时,一些从上面选择的单元格不再显示为已选择状态。当这种情况发生时,我又能够选择多个单元格,但这是不允许的。我想提一下,我尝试过在'didSelectRowAtIndexPath'中保存旧的indexPath,并在'CellForRowAtIndexPath'中进行检查,但它并不起作用:

if (old == indexpath)
{
        cell?.backgroundColor = UIColor.redColor()
        cell?.textLabel?.backgroundColor = UIColor.whiteColor() //to change only the thumbnail color and keep the cell color 
}

else {
        cell?.backgroundColor = UIColor.whiteColor()
}

现在这是我的代码

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = myTable.dequeueReusableCellWithIdentifier("WorkCell") as UITableViewCell
    cell.tag = (indexPath.row) + 1
    cell.textLabel?.text = Berufs[indexPath.row]
    var img = UIImageView(frame: CGRect(x: 10, y: 3, width: 40 , height: 40))
    cell.selectionStyle = UITableViewCellSelectionStyle.None
    img.image = UIImage(named: "transparent.png")
    cell.indentationLevel = 1
    cell.indentationWidth = 45
    cell.addSubview(img)
    return cell
}

var old = 1000

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    let indexPath = tableView.indexPathForSelectedRow()
    let cell = tableView.cellForRowAtIndexPath(indexPath!)
    var tmpCell = view.viewWithTag(old)
    var rowNum = (cell?.tag)! - 1

    if (cell?.backgroundColor == UIColor.redColor())
    {
        cell?.backgroundColor = UIColor.whiteColor()
    }
    else if (cell?.backgroundColor != UIColor.redColor())
    {
        tmpCell?.backgroundColor = UIColor.whiteColor()
        cell?.backgroundColor = UIColor.redColor()
        cell?.textLabel?.backgroundColor = UIColor.whiteColor()

        println("du interssiert dich für \(Berufs[rowNum])")
    }

    old = rowNum + 1

}
2个回答

16

目前你将选择状态存储在backgroundColor中,这不是一个好主意,因为出于性能原因,tableView会重复使用单元格。

你应该将所选的indexPaths保存在数据模型中。如果你想允许多选,可以将所选的indexPaths存储在NSMutableSet中。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    cell.selectionStyle = .None
    configure(cell, forRowAtIndexPath: indexPath)
    return cell
}

var selectedIndexPaths = NSMutableSet()

func configure(cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.textLabel!.text = "Row \(indexPath.row)"
    if selectedIndexPaths.containsObject(indexPath) {
        // selected
        cell.backgroundColor = UIColor.redColor()
    }
    else {
        // not selected
        cell.backgroundColor = UIColor.whiteColor()
    }
}


override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if selectedIndexPaths.containsObject(indexPath) {
        // deselect
        selectedIndexPaths.removeObject(indexPath)
    }
    else {
        // select
        selectedIndexPaths.addObject(indexPath)
    }
    let cell = tableView.cellForRowAtIndexPath(indexPath)!
    configure(cell, forRowAtIndexPath: indexPath)
}

如果您只需要单选,则应将所选的indexPath保存在NSIndexPath?实例变量中。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    cell.selectionStyle = .None
    configure(cell, forRowAtIndexPath: indexPath)
    return cell
}

var selectedIndexPath: NSIndexPath?

func configure(cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.textLabel!.text = "Row \(indexPath.row)"
    if selectedIndexPath == indexPath {
        // selected
        cell.backgroundColor = UIColor.redColor()
    }
    else {
        // not selected
        cell.backgroundColor = UIColor.whiteColor()
    }
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if selectedIndexPath == indexPath {
        // selected same cell -> deselect all
        selectedIndexPath = nil
    }
    else {
        // select different cell
        let oldSelectedIndexPath = selectedIndexPath
        selectedIndexPath = indexPath

        // refresh old cell to clear old selection indicators
        var previousSelectedCell: UITableViewCell?
        if let previousSelectedIndexPath = oldSelectedIndexPath {
            if let previousSelectedCell = tableView.cellForRowAtIndexPath(previousSelectedIndexPath) {
                configure(previousSelectedCell, forRowAtIndexPath: previousSelectedIndexPath)
            }
        }
    }
    let selectedCell = tableView.cellForRowAtIndexPath(indexPath)!
    configure(selectedCell, forRowAtIndexPath: indexPath)
}

这个答案非常好,而且运行得很顺畅,但是为什么有些函数前面要加上“override”呢?只要控制器实现了UITableViewDelegate,你应该只需要函数而不需要“override”,对吗? - A. Vin
非常感谢 @Matthias Bauch。 - Asif Raza

-1
我之前也遇到了同样的问题,我的解决方法是在CustomTableViewCell中添加一个新的变量(Bool),名为isset。当我第一次创建单元格时,我将其更改为true,因此当我想要重用已经设置好的单元格时,我只需返回已经设置好的单元格,以免再次设置它:
let cell = tableView.dequeueReusableCellWithIdentifier("Cellidentifier", forIndexPath: indexPath) as CustomTableViewCell

if cell.isset
{
        return cell
}

//set your cell here 
cell.isset = true
return cell

我没有找到这个函数isset,你是自己写的还是内置的? - Wild Will
你尝试运行代码了吗?还是出现了错误?有时XCode不会显示所有的方法。而且你确实在cellForRowAtIndexPath中实现了这段代码,对吧? - Dejan Skledar
"cell没有名为"isset"的成员吗?" - Dejan Skledar
我的错误,我创建了一个自定义的UITableViewCell,并添加了一个新的变量isset,然后检查它,如果单元格已经设置,我更新了答案。你知道如何创建自定义的UITableViewCell吗? - Dejan Skledar
不,看这里。我在CustomTableViewCell中将其默认设置为false,然后看一下我将其设置为true的答案。 - Dejan Skledar
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接