【问题标题】:indexPathForSelectedRow returns nil although I have a cell programmatically selected尽管我以编程方式选择了一个单元格,但 indexPathForSelectedRow 返回 nil
【发布时间】:2016-09-14 12:57:31
【问题描述】:

我有一个UITableView,我加载了一些应用程序设置。我需要表格是单选的,并且由于表格包含设置,因此可能会根据设置启用状态以编程方式选择某些单元格。

目前,我遇到了一种奇怪的行为,如果我以编程方式选择一个单元格,然后indexPathForSelectedRow 返回nil(它应该返回我选择的单元格的索引),因此当我点击第二个单元格时(更改当前选择的设置)我最终选择了两个单元格(即使我在 tableView 对象中将allowMultipleSelection 设置为 false)。

这是我的代码:

override func viewDidLoad() {
    tableView.allowsMultipleSelection = false
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("myCell")

    if let cell = cell {
        // tableObject is an array containing settings model
        let row = tableObject[indexPath.row]
        cell.textLabel!.text = row.settingValue
        if row.selected {
            cell.setSelected(true, animated: false)
            cell.accessoryType = .Checkmark
        }
        cell.tag = row.id
    }

    return cell!
}

override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
    // oldIndex is always nil for the cell I called setSelected in cellForRowAtIndexPath
    if let oldIndex = tableView.indexPathForSelectedRow {
        if let oldCell = tableView.cellForRowAtIndexPath(oldIndex) {
            tableView.deselectRowAtIndexPath(oldIndex, animated: true)
            oldCell.accessoryType = .None           
        }
    }

    if let cell = tableView.cellForRowAtIndexPath(indexPath) {
        cell.setSelected(true, animated: true)
        cell.accessoryType = .Checkmark
    }

    return indexPath
}

override func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
    if let cell = tableView.cellForRowAtIndexPath(indexPath) {
        cell.accessoryType = .None
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
    return indexPath
}

知道如何始终一次只选择一个单元格吗?

谢谢!

【问题讨论】:

  • 你需要使用 DIDSELECT 而不是 WILL SELECT 并且在方法中你已经有了 indexpath 为什么你要做像 tableView.indexPathForSelectedRow 这样的代码
  • @NitinGohel 使用上面的代码,即使我将其更改为使用 didSelectRow 我仍然观察到相同的行为
  • 让我发布一个答案,给我一些薄荷糖

标签: ios swift uitableview


【解决方案1】:

以防万一其他人遇到同样的行为,似乎通过cell.setSelected() 选择单元格与调用tableView.selectRowAtIndexPath() 方法不同。选择最新的行可以完美地完成工作并解决问题。

【讨论】:

    【解决方案2】:

    请注意,调用 tableView.reloadData() 会将 tableView.indexPathForSelectedRow 重置为零。

    这里如何通过tableView.indexPathForSelectedRow完成表格视图单选:

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
        {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.accessoryType = tableView.indexPathForSelectedRow == indexPath ? .checkmark : .none
            return cell
        }
    
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
        {
            if let visiblePaths = tableView.indexPathsForVisibleRows
            {
                for visibleIndexPath in visiblePaths
                {
                    let cell = tableView.cellForRow(at: visibleIndexPath)
                    if visibleIndexPath == indexPath
                    {
                        cell?.accessoryType = .checkmark
                    }
                    else
                    {
                        cell?.accessoryType = .none
                    }
                }
            }
        }
    

    【讨论】:

    • 是的,tableView.reloadData() 确实重置了tableView.indexPathForSelectedRow!谢谢
    【解决方案3】:

    创建一个类似的数组

    var arrSelectCell = [NSIndexPath]()
    

    并在didSelectRowAtIndexPath 处执行代码,如下所示:

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            if arrSelectCell.contains(indexPath) {
            if let oldCell = tableView.cellForRowAtIndexPath(indexPath) {
    
                    if let index = arrSelectCell.indexOf(indexPath) {
                        arrSelectCell.removeAtIndex(index)
                    }
                tableView.deselectRowAtIndexPath(indexPath, animated: true)
                oldCell.accessoryType = .None
            }
    
        }
        else
        {
            arrSelectCell.append(indexPath)
            if let selectCell = tableView.cellForRowAtIndexPath(indexPath) {
                tableView.deselectRowAtIndexPath(indexPath, animated: true)
                selectCell.accessoryType = .Checkmark
            }
    
    
        }    
    

    并且不要忘记在cellForRowAtIndexPath 中设置一个代码来检查已检查和未检查的单元格在重用单元格后是否保持。因此需要编写如下代码。

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
                let cell = tableView.dequeueReusableCellWithIdentifier("serchCell", forIndexPath: indexPath) as! SearchTableViewCell
    
                if arrSelectCell.contains(indexPath)
                {
                        cell.accessoryType = .Checkmark
                }
                else
                {
                        cell.accessoryType = .None
                }
    
                return cell
            }
    

    【讨论】:

    • 此代码不起作用,因为 ArrSelectedCell 从未被初始化。为什么它是可选的并且以大写字母开头?
    • 对资本没有任何限制,这不是目标c,因此不需要初始化。让我也给你看截图
    • 这对我来说有点像黑客。 indexPathForSelectedRow 应该返回一个NSIndexPath 对象,无论我是否使用setSelected 将我的单元格设置为选中,或者是用户点击并选择了它。
    • 大声笑,你确实需要在 Swift 中初始化数组,否则会一直是nil。以小写字母开头的变量名称是一种命名约定,它使代码更易于阅读。 (见语法高亮)。
    • 如果ArrSelectedCellnil,则不会执行所有可选的链行,例如ArrSelectedCell?.append(indexPath),因此无法工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多