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


我在这个表格视图中有一个数字列表。

enter image description here

如您所见,数字会重复出现。让我们考虑一组重复的数字作为 。所以有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
            }
        }
    }
}

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

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


12
2018-01-20 10:59


起源


您将不得不遍历您的数组并获得第一次出现的索引 groupNoToScroll。 - Hermann Klecker
但是,覆盖tableView通常不是一个好主意:willDisplayCell :.你到底在做什么? - Hermann Klecker
@HermannKlecker我想在加载所有单元格后进行自动滚动。所以根据 这个 回答, willDIsplayCell 是我需要检查的地方。有没有更好的方法来解决这个问题? - Isuru
没有willDisplayCell不是为此而设计的。你将冒无限循环的风险。我将使用scrollToRowAtIndexPath滚动到viewDidLoad中的相关单元格。工作正常。我做了很多。 - Hermann Klecker


答案:


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

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

26
2018-01-20 11:11



哇,这是一个很好的功能。非常感谢。这是非常简单和清晰的语法。很酷。 - Isuru
我不同意使用 willDisplayCell 功能虽然。我打电话后会这样做 reloadData。 stackoverflow.com/questions/16071503/... - rakeshbs
如果lastRow.row是与实际索引相对应的行,可能是每个组的大小为1时的情况,那么在这里遇到无限循环。 scrollToRowAtIndexPath可以调用willDisplayCell。 - Hermann Klecker
@HermannKlecker好的,我正在进行自动滚动 viewDidAppear 方法,因为我希望每次离开此视图并返回时都会发生滚动。 - Isuru
@rakeshbs是否有必要打电话 reloadData() 每次进行自动滚动之前?如果是这样,请告诉我原因? - Isuru


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)

8
2018-04-26 11:39





斯威夫特4:

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

(首先,当然,您必须根据要滚动到的单元格为行和部分指定值)


7
2017-12-05 12:53





这样做是为了找到数组中第一个等于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(forRow: rowToGoTo, inSection: 0)
            tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
            scrollToTime = false
        }
    }

但我建议在viewDidAppear中执行此操作。

正如Isuru指出的那样使用find函数。


1
2018-01-20 11:08



谢谢你的回答。虽然你的答案逻辑与@ rakeshbs的答案相同,但由于使用了Swift函数,我接受了他的答案 find我认为这样做更优雅,更清洁。但再次感谢:) - Isuru
这很有道理,我也愿意。我忘记了查找功能。 - Petri Oosthuizen