获取“下一个”UITableViewCell的indexPath

5

我有一个代码,用于点击表视图的单元格。在某些情况下,我想要递归调用tableView(_, didSelectRowAtIndexPath)函数以选中下一个单元格。这意味着当我选择第5行时,我想选择第6行,以此类推。

如何基于另一行获取下一个单元格的indexPath?


当您获取到indexPath时,基于indexPath + 1执行所有操作。 - Siriss
1
UITableView 中是单个部分还是多个部分? - Mrunal
@Siriss,我无法将1添加到indexPath中——它不是Int值或类似的东西。 - borchero
8个回答

8

这里是一个Swift的答案:

private func nextIndexPath(for currentIndexPath: IndexPath, in tableView: UITableView) -> IndexPath? {
    var nextRow = 0
    var nextSection = 0
    var iteration = 0
    var startRow = currentIndexPath.row
    for section in currentIndexPath.section ..< tableView.numberOfSections {
        nextSection = section
        for row in startRow ..< tableView.numberOfRows(inSection: section) {
            nextRow = row
            iteration += 1
            if iteration == 2 {
                let nextIndexPath = IndexPath(row: nextRow, section: nextSection)
                return nextIndexPath
            }
        }
        startRow = 0
    }

    return nil
}

我使用这段代码是因为我有一个包含UITextField的自定义单元格表视图。它配置了一个“下一个”按钮,当点击该按钮时,焦点会移动到下一个UITextField
要返回到上一个indexPath,请参见此答案:https://dev59.com/b4bca4cB1Zd3GeqPQwyT#56867271/ 如果想查看一个包括上一个/下一个按钮作为键盘上方工具栏的示例项目,请查看以下示例项目: https://github.com/bvankuik/TableViewWithTextFieldNextButton

1
谢谢,这对于下一个有效,但是上一个索引怎么办? - Bishal Ghimire

4

对于之前的indexPath,我已经在UITableView上创建了以下扩展(Swift 5.0)

extension UITableView {

    func previousIndexPath(currentIndexPath: IndexPath) -> IndexPath? {
        let startRow = currentIndexPath.row
        let startSection = currentIndexPath.section

        var previousRow = startRow
        var previousSection = startSection

        if startRow == 0 && startSection == 0 {
            return nil
        } else if startRow == 0 {
            previousSection -= 1
            previousRow = numberOfRows(inSection: previousSection) - 1
        } else {
            previousRow -= 1
        }

        return IndexPath(row: previousRow, section: previousSection)
    }

}

2
很好,这是一种非常自然的方式将其制作为扩展。 - Bart van Kuik
请点击此处查看上述方法的nextIndexPath()版本。 - Eric33187
可能是一个小疏忽:一个部分可以包含零行。如果你回到了一个之前有零行的部分,你会返回一个row = -1的indexPath(numberOfRows(...) - 1)吗? - andreas1724
@andreas1724:对于零行部分,不会使用indexPath,因为在这种情况下不会调用Row For Index Path。此外,这只是IndexPath的帮助程序。因此,零行的概念无效,因为这只涉及IndexPath。最后,由于此具有可选返回类型,因此row==0的情况也不会出现问题,这是在代码中首先返回检查的IF条件。 - Bishal Ghimire
@Bishal Ghimire:初始的currentIndexPath不是问题所在。我同意你的观点,即currentIndexPath没有指向零行部分。但请考虑以下情况:第0节有一行。第1节有零行(这是有效的)。第2节有一行。currentIndexPath指向第2节的第一行。如果您尝试计算前面的单元格IndexPath,则会得到IndexPath [1,-1]。它应该是[0,0]。 - andreas1724

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

    let nextIndexPath=NSIndexPath(forRow: indexPath.row + 1, inSection: indexPath.section);

    // You should be sure than this NSIndexPath exist, and ...make what you want

}

@DavidRönnqvist,很抱歉,但我理解这是问题:“如何基于另一行获取下一个单元格的indexPath?”。 这是答案:“let nextIndexPath = NSIndexPath(forRow:indexPath.row + 1,inSection:indexPath.section);”。 这个人没有任何代码不工作或代码有问题。 无论如何,我不知道如何提供更多的解释。 抱歉。 - Onik IV
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - borchero
@DavidRönnqvist 你说得对。通常我都尽量解释清楚,但这次我认为足够了。别担心,下一次我会添加更多的解释。谢谢。 - Onik IV
2
如果下一行在下一节中,则此方法将无效。 - user3246173
@OnikIV 你说:“你应该确保这个NSIndexPath存在”,我该怎么做?(我也遇到了同样的问题) - Stanislav Putilov
显示剩余2条评论

1
这将适用于Swift 4,用于上一个和下一个。
let nextIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section)
let previousIndexPath = IndexPath(row: indexPath.row - 1, section: indexPath.section)

1

目前,我认为只有Bart van Kuiks的答案考虑了一个部分可能不包含任何行的情况。

enter image description here

其他帖子的作者可能会更正他们的回答。与此同时,我发布了我的代码,用于下一个和上一个单元格作为 UITableView 扩展。如果您发现任何错误,请随意编辑代码。

extension UITableView {

    func indexPathOfCell(after indexPath: IndexPath) -> IndexPath? {
        var row = indexPath.row + 1
        for section in indexPath.section..<numberOfSections {
            if row < numberOfRows(inSection: section) {
                return IndexPath(row: row, section: section)
            }
            row = 0
        }
        return nil
    }
    
    func indexPathOfCell(before indexPath: IndexPath) -> IndexPath? {
        var row = indexPath.row - 1
        for section in (0...indexPath.section).reversed() {
            if row >= 0 {
                return IndexPath(row: row, section: section)
            }
            if section > 0 {
                row = numberOfRows(inSection: section - 1) - 1
            }
        }
        return nil
    }

}

1

我写了一个IndexPath扩展方法,我发现它的逻辑比@Bart van Kuik的解决方案更容易理解。

用Swift 5编写,Xcode 11,适用于多节UITableView。

import UIKit

extension IndexPath {

    // Helper Methods
    func incrementRow(plus: Int=1) -> IndexPath {
        return IndexPath(row: row + plus, section: section)
    }

    func incrementSection(plus: Int=1) -> IndexPath {
        return IndexPath(row: 0, section: section + plus)
    }

    func next(in table: UITableView) -> IndexPath? {
        // if can find cell for next row, return next row's IndexPath
        if let _ = table.cellForRow(at: incrementRow()) {
            return incrementRow()
        }
        // cannot find next row, try to find row 0 in next section
        else if let _ = table.cellForRow(at: incrementSection()) {
            return incrementSection()
        }

        // can find neither next row nor next section, the current indexPath is already the very last IndexPath in the given table
        return nil
    }    
}

关于之前的IndexPath,@Bishal Ghimire的回答是有效的,但这里提供了IndexPath版本的扩展。
func previous(in table: UITableView) -> IndexPath? {
        // if the current indexPath is the very first IndexPath, then there's no previous
        if row == 0 && section == 0 { return nil }

        // if the current indexPath is the first row in a section, return table's previous section's last row's IndexPath
        if row == 0 {
            let lastRowInPrevSection = table.numberOfRows(inSection: section - 1) - 1
            return IndexPath(row: lastRowInPrevSection, section: section - 1)
        }
        // else just return previous row's IndexPath in the same section
        else {
            return IndexPath(row: row - 1, section: section)
        }
    }

您可以将这些方法拖放到任何项目中并直接使用,例如,在我的情况下,我正在尝试在用户按下回车键时突出显示下一个单元格的textField,因此使用方式如下:
...
if let nextIndexPath = currentIndexPath.next(in: myTableView),
   let nextCell = myTableView.cellForRow(at: nextIndexPath) as? MyCell {
   nextCell.textField.becomeFirstResponder()
} else {
   // there's no next IndexPath in the given table, simply resign first responder for the current cell's textField
   currentCell.textField.resignFirstResponder()
}
...

0

对于那些喜欢 @Bishal Ghimire 的 previousIndexPath() 方法的人,这里是 nextIndexPath() 方法的实现。

import UIKit

extension UITableView {

    func nextIndexPath(currentIndexPath: IndexPath) -> IndexPath? {
        let startRow = currentIndexPath.row
        let startSection = currentIndexPath.section

        var nextRow = startRow
        var nextSection = startSection

        if startSection == numberOfSections-1 && startRow == numberOfRows(inSection: startSection)-1 {
            return nil
        } else if startRow == numberOfRows(inSection: startSection)-1 {
            nextSection += 1
            nextRow = 0
        } else {
            nextRow += 1
        }

        return IndexPath(row: nextRow, section: nextSection)
    }
}

-2

您可以获取Object的IndexOFO

NSUInteger indexOfTheObject = [Array indexOfObject:indexPath];

对于单元格点击:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *temp = [Array objectAtIndex:indexPath.row+1]; 
temp...


}

1
他们没有在编写 Obj C 代码。 - soulshined

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