12

Prior to swift 3, i used to use for example:

let path = self.tableView.indexPathForSelectedRow
if (path != NSNotFound) {
//do something
 }

But now, since i use IndexPath class in swift3, i'm looking for the equivalent for the path != NSNotFound check.

Xcode8.3.1 compiler error: "Binary operator '!=' cannot be applied to operands of type 'IndexPath' and 'Int'"

Lirik
  • 3,167
  • 1
  • 30
  • 31
  • 3
    Why would you check it like this? There's no way that code ever worked as-is since you can't compare `NSIndexPath` against `NSNotFound`. – rmaddy Apr 25 '17 at 15:22
  • 1
    The NSIndexPath initializer simply creates an object. In what way do you expect initializing an NSIndexPath where it is 'NotFound'? This is not a query. You might be mixing it with 'indexOf', which returns an optional that can be checked for nil. – bauerMusic Apr 25 '17 at 15:22
  • @bauerMusic, that was just a bad example. I was referring more to methods that return IndexPath. That would have been a better example ;) updated the question – Lirik Apr 25 '17 at 15:32
  • Given your update, what's you definition of a valid index path? Is it simply whether the result is `nil` or not? – rmaddy Apr 25 '17 at 15:37
  • And you really should post code that actually worked for you under Swift 2 but is now giving you trouble under Swift 3. – rmaddy Apr 25 '17 at 15:38
  • 3
    I'm quite sure that `indexPathForSelectedRow` returned `nil` rather than `NSNotFound` even in Swift 2. – vadian Apr 25 '17 at 15:50

4 Answers4

23

To check if IndexPath exists, I use this extension function:

import UIKit

extension UITableView {

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
    }
}

And to use it I do something like this:

if tableView.hasRowAtIndexPath(indexPath: indexPath) {
    // do something
}
pableiros
  • 14,932
  • 12
  • 99
  • 105
  • Thanks for this. I think this should be in a must-included extension. – Seto Apr 10 '18 at 06:32
  • 1
    I have an NSFetchedResultsController that's returning an index path with a row index of -1. So it might be worth checking for >= 0 as well. – Murray Sagal Jan 05 '19 at 17:02
  • 1
    This gives me `EXC_BAD_ACCESS (code=1, address=0xfffffffffffffff8) numberOfRows`. My indexpath is `[-1, -1]` – Parth Jan 15 '21 at 06:31
  • Nevermind got the issue. The logic check is incomplete. – Parth Jan 15 '21 at 06:37
11

Semantically, to consider an indexPath invalid, you need something to check for such as a table view or a collection view.

Usually you can consider an indexPath invalid if it represents a row where there is no corresponding data in the data source. (One exception would be "Load more" rows.)

If you really need to create an invalid IndexPath, you can do:

let invalidIndexPath = IndexPath(row: NSNotFound, section: NSNotFound)

After the update:

self.tableView.indexPathForSelectedRow returns an Optional so can be nil if there is no selected row.

if let path = tableView.indexPathForSelectedRow {
  // There is a selected row, so path is not nil.
}
else {
  // No row is selected.
}

Anyway, comparing path against NSNotFound raises an exception in all cases.

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
3

Improving the answer by @pableiros to handle edge case where section or row less than 0. This will happen when the table is empty and you try to access it by listOfSectionHeaders.count - 1, listOfRowsForSection.count - 1

extension UITableView {
    func isValid(indexPath: IndexPath) -> Bool {
        return indexPath.section >= 0 
            && indexPath.section < self.numberOfSections 
            && indexPath.row >= 0 
            && indexPath.row < self.numberOfRows(inSection: indexPath.section)
    }
}
Parth
  • 2,682
  • 1
  • 20
  • 39
0

I stumbled on a case where collectionView(_:didEndDisplaying:forItemAt:) returns an invalid indexPath, so I used indexPath.isEmpty to check whether indexPath was indeed a row/section indexPath.

CiNN
  • 9,752
  • 6
  • 44
  • 57