13

Sometimes when I tried to scroll a tableview to a row, I can unexpectedly supply a nonexistent section/row. And then the app will crash.

self.tableView.scrollToRow(at: IndexPath(row: targetRow, section: targetSection), at: UITableViewScrollPosition.bottom, animated: true);

How can I make this scrolling process crash-safe? I mean, if I do supply a nonexistent section/row, I want UITableView just ignore it. Or how can I check whether a section/row is exist or not within a UITableView before I do the scroll? Thanks.

Chen Li Yong
  • 4,659
  • 6
  • 50
  • 101

2 Answers2

19

Use this UITableView extension to check whether a Indexpath is valid.

extension UITableView
{
    func indexPathExists(indexPath:IndexPath) -> Bool {
        if indexPath.section >= self.numberOfSections {
            return false
        }
        if indexPath.row >= self.numberOfRows(inSection: indexPath.section) {
            return false
        }
        return true
    }
}

Use like this

var targetRowIndexPath = IndexPath(row: 0, section: 0)
if table.indexPathExists(indexPath: targetRowIndexPath)
{
  table.scrollToRow(at: targetRowIndexPath, at: .bottom, animated: true)
}
RajeshKumar R
  • 14,770
  • 2
  • 37
  • 67
11

Try this --

let indexPath = IndexPath(row: targetRow, section: targetSection)
if let _ = self.tableView.cellForRow(at: indexPath) {
 self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true)
}
Aditya Srivastava
  • 2,595
  • 2
  • 11
  • 23
  • Oooouw clever! I forgot about that `cellForRow` function. Thanks! – Chen Li Yong Sep 29 '17 at 07:20
  • I think using "guard" would be even better alternative right since its especially used to avoid crashes ? like guard let _ = self.tableView.cellForRow(at: indexPath) else { return } – Bharath Sep 29 '17 at 07:57
  • @Bharath It depends where we are using it. There is no such like guard is better alternative for crash. It is just like returning from there only if the nil is found in the condition.. But if let just checks the condition if it's nil then also the remaining code of line will execute. You can check this [link also](https://stackoverflow.com/questions/32256834/swift-guard-vs-if-let) – Aditya Srivastava Sep 29 '17 at 08:22
  • @AdityaSrivastava : Well explained, thanks for the info. – Bharath Sep 29 '17 at 08:59
  • Usually I use guard if I want to avoid indentation hell in swift. https://thatthinginswift.com/guard-statement-swift/ BUT guard is unfit if we still need to run other lines of code unrelated to the condition, just like what Aditya has explained. – Chen Li Yong Oct 02 '17 at 02:51
  • 6
    Warning: cellForRow gets nil if the cell is not visible. – orafaelreis Jun 21 '19 at 13:10
  • @orafaelreis Yes, that's why I have used `if let` while calling `cellForRow` – Aditya Srivastava Jun 22 '19 at 06:04
  • 1
    @AdityaSrivastava if you need to scroll to some cell out of bound of visibility this won't help you. – orafaelreis Jun 22 '19 at 17:14
  • @orafaelreis Correct. But the question is how to scroll safely not scrolling to indexpath which is not visible. – Aditya Srivastava Jun 24 '19 at 06:32