user7219266
user7219266

Reputation:

iOS - NSInternalInconsistencyException happens on iOS 9 and 10 but working fine on iOS 11

This is the error I am getting on devices with iOS 9 and 10 :

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for number of items before section 9223372036854775807 when there are only 1 sections in the collection view'

The error seems clear to me, however I am unable to understand why this is not happening on devices with iOS 11.

I don't know how to fix it.

Here is my code :

extension MainTileViewController: MainForecastsDelegate {
func mainForecasts(_ forecastVC: MainForecastsViewController!, didChangeWith object: Any!) {
    if let cell = self.outletWeatherForecastCollectionView.cellForItem(at: self.currentIndexPath) as? MainTileCollectionViewCell { 
        // Some stuff...
    }
}

The crash happens here. This is a protocol method triggered when the user switch day etc...

Obviously I have an issue with my currentIndexPath.

Here is my initialization :

 var currentIndexPath : IndexPath = []

And in the viewDidLoad :

self.currentIndexPath = IndexPath(item: 0, section: 0)

How can I secure my code so that it won't crash ? Can you explain me the changing behavior between collectionView from iOS 9/10 with iOS 11 ones (except prefetching).

Upvotes: 1

Views: 454

Answers (2)

Mike Mertsock
Mike Mertsock

Reputation: 12015

What's happening is that setting currentIndexPath = [] is not assigning any value to its item or section; it's creating an "empty" IndexPath (IndexPath objects are basically arbitrary-length tuples or arrays of values and can be created/manipulated as such). Any code attempting to use it in that way (such as passing it to a cellForItem call) will have potentially undefined behavior. Looks like something is effectively interpreting the missing section value as -1, and then something else is interpreting that -1 as an unsigned 64-bit integer.

Instead, if you want to use the same general logic that you have now, I'd suggest declaring indexPath as an optional:

var currentIndexPath: IndexPath?

Then, use if-let syntax in your usages of currentIndexPath:

extension MainTileViewController: MainForecastsDelegate {
func mainForecasts(_ forecastVC: MainForecastsViewController!, didChangeWith object: Any!) {
    if let currentIndexPath = currentIndexPath,
        let cell = outletWeatherForecastCollectionView.cellForItem(at: currentIndexPath) as? MainTileCollectionViewCell { 
        // Some stuff...
    }
}

This follows Swift idioms and makes clear the concept that you start with an "unknown" index path.

But - as @picciano's answer suggests, you may want to rethink your overall design to better fit the larger design patterns of iOS apps.

Upvotes: 3

picciano
picciano

Reputation: 22701

I would suggest changing your approach a bit. Let your collection view cell subclass be responsible for updating itself, perhaps from a notification. Trying to retain an index path or reference to a cell will always be problematic given their tendency to be reused.

Upvotes: 0

Related Questions