README and documentationIGListKit version: 1.0 Master ThreadI have my workingRangeDelegate set, with a range of 2.
If you adjust the DemosViewController so that you:
demos2 where it's defined as var demos2: [DemoItem] = [])sectionControllerWillEnterWorkingRange function by using the following code:if let cell = self.collectionContext?.cellForItem(at: 0, sectionController: self) as? LabelCell {
print("hey!")
}
It will crash with the following exception:
'NSInternalInconsistencyException', reason: 'request for number of items before section 2 when there are only 0 sections in the collection view'
I initially encountered it within my own project but found it to be reproducible using the steps above!
@yusuftor why are you accessing the cell in -sectionControllerWillEnterWorkingRange:? If you just entered the range you shouldn't have a cell yet. If you remove that line does it still repro?
@rnystrom Ok I'm a bit confused then.
In the WorkingRangeSectionController in the example project, it accesses the cell in -sectionControllerWillEnterWorkingRange: using the same code as I just tried to use. It does that to set the image in the cell, and I'm also trying to set something within the cell. But if you say that you shouldn't have access, why does the example project access it?
And no it doesn't crash if I remove that line.
What happens if you're scrolling, download a large image that takes a while in -sectionControllerWillEnterWorkingRange: and set a property downloadedImage with the new image. As that image is being downloaded -cellForItem: might be called, but at that moment downloadedImage hasn't been set. Eventually downloadedImage would be set, but if the cell isn't accessible in -sectionControllerWillEnterWorkingRange: the cell image would be nil until -cellForItem: is called again.
I think this is the problem that has happened to me when I have small section controllers (150px in height) with a small workingRange. I've had to increase the working range just so that -sectionControllerWillEnterWorkingRange: can set the downloadedImage property before -cellForItem: is called.
@yusuftor the idea in that project is that if in the time since you started downloading, a cell exists, then assign the image data to that cell's image view. (your fourth paragraph is spot on)
It does seem like there is a real crash/issue in here though. I'll get the sample into the config that you outlined and see what is going on. Either a UICollectionView annoyance that we can avoid by returning nil, or a bug in the working range stuff.
Thanks for all the detail!
@rnystrom That makes sense. That's why I've been trying to access the cell to update it, but the occasional crash issue has prevented me from doing that.
No worries, if you need any extra info from me let me know!
I just encountered this same error again. I decided to investigate and the place where it crashes is in IGListAdapter.m in this function:
- (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index
sectionController:(IGListSectionController <IGListSectionType> *)sectionController {
IGAssertMainThread();
IGParameterAssert(sectionController != nil);
// if this is accessed while a cell is being dequeued, just return nil
if (_isDequeuingCell) {
return nil;
}
NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index];
// prevent querying the collection view if it isn't fully reloaded yet for the current data set
if (indexPath != nil
&& indexPath.section < [self.collectionView numberOfSections]) {
// only return a cell if it belongs to the section controller
// this association is created in -collectionView:cellForItemAtIndexPath:
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
if ([self sectionControllerForCell:cell] == sectionController) {
return cell;
}
}
return nil;
}
Specifically on the line: UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];. I tried printing out the number of sections in the collectionView and it correctly prints out the number that should be in the collectionView... Yet at the same time the error is saying that there are 0 items!
I tried to trace -performUpdates: and that goes all the way through until it reaches the line [collectionView performBatchUpdates:updateBlock completion:completionBlock]; in -performBatchUpdatesWithCollectionView: inside IGListAdapterUpdater.m. It does everything in the updateBlock, but then the exception occurs so the completion block never happens. Perhaps what's happening is that the workingRangeDelegate is being called before the collectionView has updated properly?
Hopefully this extra info can help you! If I find any more info I'll update this thread...
@yusuftor -- Can you provide repro steps or a stack trace?
@jessesquires Repro steps are the same as in my first post. The stack trace is :
2016-11-14 10:44:03.223 IGListKitExamples[78257:9572078] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for number of items before section 2 when there are only 0 sections in the collection view'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cf3434b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010c99521e objc_exception_throw + 48
2 CoreFoundation 0x000000010cf38442 +[NSException raise:format:arguments:] + 98
3 Foundation 0x000000010c52be4d -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 UIKit 0x000000010e66f661 -[UICollectionViewData numberOfItemsBeforeSection:] + 231
5 UIKit 0x000000010e66f70d -[UICollectionViewData globalIndexForItemAtIndexPath:] + 52
6 UIKit 0x000000010e61b542 -[UICollectionView _cellForItemAtIndexPath:includePrefetchedCells:] + 118
7 IGListKit 0x000000010c3d34d4 -[IGListAdapter cellForItemAtIndex:sectionController:] + 1236
8 IGListKitExamples 0x000000010c24b75b _TFC17IGListKitExamples21DemoSectionController11listAdapterfTCSo13IGListAdapter38sectionControllerWillEnterWorkingRangeCSo23IGListSectionController_T_ + 155
9 IGListKitExamples 0x000000010c24b98f _TToFC17IGListKitExamples21DemoSectionController11listAdapterfTCSo13IGListAdapter38sectionControllerWillEnterWorkingRangeCSo23IGListSectionController_T_ + 79
10 IGListKit 0x000000010c408aeb -[IGListWorkingRangeHandler updateWorkingRangesWithListAdapter:] + 10699
11 IGListKit 0x000000010c405a8d -[IGListWorkingRangeHandler willDisplayItemAtIndexPath:forListAdapter:] + 6189
12 IGListKit 0x000000010c3d1a54 -[IGListAdapter collectionView:willDisplayCell:forItemAtIndexPath:] + 660
13 UIKit 0x000000010e60a116 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 2409
14 UIKit 0x000000010e6097a7 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 35
15 UIKit 0x000000010e628c28 __51-[UICollectionView _viewAnimationsForCurrentUpdate]_block_invoke.1912 + 597
16 UIKit 0x000000010e625753 -[UICollectionView _viewAnimationsForCurrentUpdate] + 3529
17 UIKit 0x000000010e62b7e1 __71-[UICollectionView _updateWithItems:tentativelyForReordering:animator:]_block_invoke.1983 + 197
18 UIKit 0x000000010dd806e6 +[UIView(Animation) performWithoutAnimation:] + 90
19 UIKit 0x000000010e62a337 -[UICollectionView _updateWithItems:tentativelyForReordering:animator:] + 3942
20 UIKit 0x000000010e624369 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 17765
21 UIKit 0x000000010e62cdba -[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:] + 71
22 UIKit 0x000000010e62d0fc -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 432
23 UIKit 0x000000010e62cf29 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 91
24 UIKit 0x000000010e62ceab -[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 74
25 UIKit 0x000000010e62ce00 -[UICollectionView performBatchUpdates:completion:] + 53
26 IGListKit 0x000000010c3de5fc -[IGListAdapterUpdater performBatchUpdatesWithCollectionView:] + 2956
27 IGListKit 0x000000010c3e1535 __54-[IGListAdapterUpdater queueUpdateWithCollectionView:]_block_invoke + 357
28 libdispatch.dylib 0x000000010ff6d980 _dispatch_call_block_and_release + 12
29 libdispatch.dylib 0x000000010ff970cd _dispatch_client_callout + 8
30 libdispatch.dylib 0x000000010ff778d6 _dispatch_main_queue_callback_4CF + 406
31 CoreFoundation 0x000000010cef84f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
32 CoreFoundation 0x000000010cebdf8d __CFRunLoopRun + 2205
33 CoreFoundation 0x000000010cebd494 CFRunLoopRunSpecific + 420
34 GraphicsServices 0x00000001111b5a6f GSEventRunModal + 161
35 UIKit 0x000000010dcc7964 UIApplicationMain + 159
36 IGListKitExamples 0x000000010c25df7f main + 111
37 libdyld.dylib 0x000000010ffe368d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Would it be possible to look into this bug before v2.0 is released? It seems like a fairly major bug to me as until this is fixed I can't reliably use the working range in production. No worries if not though as I know you guys are working really hard on other issues. As a side note, IGListKit has made the scrolling within my app waaay smoother than before, so thanks for that!
@yusuftor I'm on this today, ideally I should be able to make a repro unit test and fix the crash. Very bizarre. Agree tho this should be fixed before 2.0.
Haven't fixed it, but do have my sample project in a setup where this crash occurs.
Most helpful comment
Haven't fixed it, but do have my sample project in a setup where this crash occurs.