尽管我以编程方式选择了一个单元格,但 indexPathForSelectedRow 返回 nil

Posted

技术标签:

【中文标题】尽管我以编程方式选择了一个单元格,但 indexPathForSelectedRow 返回 nil【英文标题】:indexPathForSelectedRow returns nil although I have a cell programmatically selected 【发布时间】: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 我仍然观察到相同的行为 让我发布一个答案,给我一些薄荷糖 【参考方案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),因此无法工作。

以上是关于尽管我以编程方式选择了一个单元格,但 indexPathForSelectedRow 返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

为啥我无法在 collectionView 中选择单元格?

FullCalendar Jquery,选择内天

UICollectionView 正在显示,但单元格未快速显示

为啥以编程方式选择单元格后 - 单元格不是交互?

在iOS中选择单元格时如何以编程方式更改原型单元格中的标签文本颜色和图像

Swift - 表格视图单元格内的单击按钮不会在该单元格的功能处调用确实选择行