Swift中的indexPathsForSelectedRows返回nil

5
我正在处理一个tableView,目标是实现可展开/折叠的tableView单元格。单元格的数量是完全动态的。
我已经有了一些东西在运作,但存在一个小问题。我使用didSelectRowAtIndexPath来切换展开/折叠单元格。所以现在发生的是,通过在单元格上的任何位置点击来执行切换。 :-(
在单元格内部,我有两个UIView(Header和Detail)。我需要在点击Header而不是整个单元格时才能切换展开/折叠。
为此,我像这样获取indexPath,但它不起作用,因为indexPathsForSelectedRows返回nil。
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }


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

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if selectedIndex == indexPath.row {
            return 150.0
        }
        else {
            return 40.0
        }
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        cell = tableView.dequeueReusableCellWithIdentifier("CollapsedCell", forIndexPath: indexPath) as! CollapsedCell

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(VoucherDetailViewController.expandCell(_:)))
        (cell as! CollapsedCell).headerView.addGestureRecognizer(tapGestureRecognizer)

        return cell
    }

    func getIndexPathForSelectedCell() -> NSIndexPath? {

        var indexPath: NSIndexPath?

        if tableView.indexPathsForSelectedRows?.count > 0 {   //**nil is returned here**
            indexPath = (tableView.indexPathsForSelectedRows?[0])! as NSIndexPath
        }
        return indexPath
    }

    func expandCell(sender: UITapGestureRecognizer) {
        if let myIndexPath = getIndexPathForSelectedCell() {
            if selectedIndex == myIndexPath.row {
                selectedIndex = -1
            }
            else {
                selectedIndex = myIndexPath.row
            }

            self.tableView.beginUpdates()
            self.tableView.reloadRowsAtIndexPaths([myIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
            self.tableView.endUpdates()
        }
    }

有人能给我一个线索,为什么indexPathsForSelectedRows返回nil吗?

非常感谢!

更新 1: 当前的工作演示

当我在didSelectRowAtIndexPath中添加我的展开单元格逻辑并删除单元格内视图的tapGestureRecognizer时,它看起来像这样 -

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        if selectedIndex == indexPath.row {
            selectedIndex = -1
        }
        else {
            selectedIndex = indexPath.row
        }

        self.tableView.beginUpdates()
        self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        self.tableView.endUpdates()
    }
3个回答

3
你遇到了这个错误是因为
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)

重新加载并取消选择你的行。

你只是先选择了一行,然后重新加载该行(此操作将取消选择该行),然后你想使用

来获取所选行。

tableView.indexPathsForSelectedRows

但是此时表视图没有选中的行。

作为一个解决方案,您可以将选中的indexPath存储到一个新变量中,并使用该变量代替

tableView.indexPathsForSelectedRows

有道理!将所选的indexPath存储在新变量中 - 你可以详细说明一下吗? - Lohith Korupolu
@LohithKorupolu,在你的控制器中创建一个变量,并在didSelectRowAtIndexPath方法中将indexPath的新值保存到这个变量中。 - Vlad Khambir
我应该在单元格中使用didSelectRowAtIndexPath或tapGesture。如果我两个都用,只有tapGesture能工作,而didSelectRowAtIndexPath不能工作。 - Lohith Korupolu
我的问题是如何仅通过点击HeaderView而不是整个单元格来执行切换逻辑。 - Lohith Korupolu

1

indexPathsForSelectedRows文档中得知:

如果没有选中行,则此属性的值为nil。

因此:

guard let selectedRows = tableView.indexPathsForSelectedRows else {
   return nil
}

return selectedRows[0]

不需要检查 count,该方法从不返回空数组。

顺便提一下,您可以使用以下方式简化条件:

return tableView.indexPathsForSelectedRows?.first

或者,如果您的表格不支持多选,直接调用:
return tableView.indexPathForSelectedRow

已经存在。


1
是的,这就是问题所在。即使我选择了一行,tableView.indexPathForSelectedRow总是返回nil。我该如何解决这个nil问题? - Lohith Korupolu
@LohithKorupolu,如果在此之前重新加载了表视图数据,则tableView.indexPathForSelectedRow将始终返回nil。因为重新加载数据后,表视图会重置所有单元格的选择状态。 - Vlad Khambir
2
@V.Khambir 如果您需要保留选择,请不要重新加载单元格。如果您只需要更新单元格的高度,请不要调用reloadRowsAtIndexPaths方法。只需在beginUpdatesendUpdates之间调用这两个方法即可。 - Sulthan

0
正如Sulthan所说,尝试使用以下代码替换reload。
tableView.beginUpdates()
tableView.endUpdates()

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