自动滚动到具有特定值的单元格

22
我有一个数字列表,像这样在表格视图中显示。
如您所见,数字是重复的。让我们将一组重复的数字称为“组”。因此,有1的组,2的组等等。
我想要做的是当应用程序启动时,我需要自动滚动到指定组的起始位置。在进一步解释之前,这是我的代码。
import UIKit

class TableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {

    private var scrollToTime = true
    private var items = [Int]()
    private var groupNoToScroll = 12

    override func viewDidLoad() {
        super.viewDidLoad()

        items = [1, 1, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20, 21, 22, 22, 23, 23, 23]
    }

    // MARK: - UITableViewDataSource
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        cell.textLabel?.text = String(items[indexPath.row])

        return cell
    }

    // MARK: - UITableViewDelegate
    override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

        let lastRow = tableView.indexPathsForVisibleRows()?.last as NSIndexPath
        if indexPath.row == lastRow.row {
            if scrollToTime == true {
                let indexPath = NSIndexPath(forRow: groupNoToScroll, inSection: 0)
                tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
                scrollToTime = false
            }
        }
    }
}

我已经将变量groupNoToScroll的值设置为12。这意味着当应用程序启动时,我希望表视图自动滚动到12组单元格的开头。

但目前我的代码滚动到第12个单元格,而不是具有 12的单元格。我的问题是如何检查单元格的值并滚动到我指定的数字?


1
你需要遍历数组并获取groupNoToScroll第一次出现的索引。 - Hermann Klecker
1
然而,通常不建议覆盖tableView:willDisplayCell:方法。你真正想做什么? - Hermann Klecker
@HermannKlecker,我想在所有单元格加载完成后执行自动滚动。因此,根据这个答案,我需要在willDIsplayCell中检查。有更好的方法吗? - Isuru
不,willDisplayCell并不是为此而设计的。你会冒着无限循环的风险。我建议在viewDidLoad中使用scrollToRowAtIndexPath来滚动到相关单元格。这样做很好用,我经常这么做。 - Hermann Klecker
4个回答

52

您可以使用 find 函数查找项的索引(这将是它的行),然后滚动到该索引。
find 函数返回数组中特定元素的索引。

if let index = find(items, groupNoToScroll)
{
    let indexPath = NSIndexPath(forRow: index, inSection: 0)
    tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

哇,这是一个很棒的函数。非常感谢。这个语法出奇的简单和清晰。非常酷。 - Isuru
如果lastRow.row正是对应实际索引的那一行,这可能在每个组的大小为1时发生,那么你会陷入一个无限循环。scrollToRowAtIndexPath可能会导致willDisplayCell被调用。 - Hermann Klecker
1
@HermannKlecker 好的,我在 viewDidAppear 方法中实现了自动滚动,因为我希望每次离开并返回此视图时都发生滚动。 - Isuru
@rakeshbs 在执行自动滚动之前,每次都需要调用reloadData()吗?如果是这样,请告诉我原因。 - Isuru
你需要定义一个函数来找到下一个最接近的值,然后滚动到它。目前没有内置的方法可以实现这个功能。 - rakeshbs
显示剩余4条评论

20

Swift 4:

let indexPath = IndexPath(row: row, section: section)
tableView.scrollToRow(at: indexPath, at: .top, animated: true)

首先,当然,您需要根据要滚动到的单元格分配行和列的值。


12

Swift 3.0

 let indexPath = NSIndexPath(forRow: 5, inSection: 0)
 tableView.scrollToRow(at: indexPath, at: .top, animated: true)

Swift 4.0

let lastRowIndex = self.tblRequestStatus!.numberOfRows(inSection: 0) - 1
let pathToLastRow = IndexPath.init(row: lastRowIndex, section: 0)
tableView.scrollToRow(at: pathToLastRow, at: .none, animated: false)

3

执行此操作以查找数组中第一个等于groupNoToScroll的元素。然后,转到该行。

    var rowToGoTo:Int = 0 //Rather use the Swift find function.
    for x in items{
        if x == groupNoToScroll{
            break
        }
        rowToGoTo++
    }

    let lastRow = tableView.indexPathsForVisibleRows()?.last as NSIndexPath
    if indexPath.row == lastRow.row {
        if scrollToTime == true {
           let indexPath = NSIndexPath(row: rowToGoTo, section: 0)
           tblBusList.scrollToRow(at: indexPath as IndexPath, at: .top, animated: true)
        }
    }

我建议在viewDidAppear方法中完成这个操作。

正如Isuru所指出的,最好使用find函数。


谢谢你的回答。虽然你的回答逻辑与@rakeshbs的回答相同,但我接受了他的回答,因为他使用了Swift函数“find”,我认为这是一种更优雅和更清晰的方法。但还是再次感谢 :) - Isuru
那很有道理,我也会这样做。我忘记了查找函数。 - Petri

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