Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when calling performUpdates with workingRangeDelegate #177

Closed
2 tasks done
yusuftor opened this issue Nov 8, 2016 · 10 comments
Closed
2 tasks done

Crash when calling performUpdates with workingRangeDelegate #177

yusuftor opened this issue Nov 8, 2016 · 10 comments
Labels
Milestone

Comments

@yusuftor
Copy link

yusuftor commented Nov 8, 2016

New issue checklist

General information

  • IGListKit version: 1.0 Master Thread
  • iOS version(s): 10
  • CocoaPods/Carthage version: 1.1
  • Xcode version: 8
  • Devices/Simulators affected: All
  • Reproducible in the demo project? (Yes/No): Yes
  • Related issues:

I have my workingRangeDelegate set, with a range of 2.

If you adjust the DemosViewController so that you:

  1. Initially return zero items to your Adapter Data Source (return a property demos2 where it's defined as var demos2: [DemoItem] = [])
  2. Try to access a cell in your sectionControllerWillEnterWorkingRange function by using the following code:
if let cell = self.collectionContext?.cellForItem(at: 0, sectionController: self) as? LabelCell {
    print("hey!")
}
  1. Change the adapter data source to have some items upon viewWillAppear (imitating loading some data from the server). (set demos2 = demos).
  2. Then run performUpdates in viewWillAppear straight after that.

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!

@rnystrom
Copy link
Contributor

rnystrom commented Nov 8, 2016

@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?

@yusuftor
Copy link
Author

yusuftor commented Nov 8, 2016

@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.

@rnystrom
Copy link
Contributor

rnystrom commented Nov 8, 2016

@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!

@yusuftor
Copy link
Author

yusuftor commented Nov 8, 2016

@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!

@yusuftor
Copy link
Author

yusuftor commented Nov 11, 2016

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...

@jessesquires
Copy link
Contributor

@yusuftor -- Can you provide repro steps or a stack trace?

@yusuftor
Copy link
Author

@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

@yusuftor
Copy link
Author

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!

@rnystrom
Copy link
Contributor

@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.

@rnystrom rnystrom added this to the 2.0.0 milestone Nov 16, 2016
@rnystrom
Copy link
Contributor

Haven't fixed it, but do have my sample project in a setup where this crash occurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants