Instagram / IGListKit

A data-driven UICollectionView framework for building fast and flexible lists.
https://instagram.github.io/IGListKit/
MIT License
12.86k stars 1.54k forks source link

App crash whenever adding left/right contentInset in UICollectionView. #1364

Open tarunbhutani opened 5 years ago

tarunbhutani commented 5 years ago

App is crashing whenever giving left and right contentInset to UICollectionView.

collectionView.contentInset = UIEdgeInsets(
                top: view.safeAreaInsets.top + 20,
                left: 16,
                bottom:  tabbarHeight + miniplayerHeight + 20,
                right: 16
            )

Error:

*** Assertion failure in -[IGListCollectionViewLayout _calculateLayoutIfNeeded](),

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Width of item 0 in section 10 (414 pt) must be less than or equal to container (382 pt) accounting for section insets {0, 0, 0, 0}'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010c6568db __exceptionPreprocess + 331
    1   libobjc.A.dylib                     0x000000010bbf9ac5 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010c656662 +[NSException raise:format:arguments:] + 98
    3   Foundation                          0x0000000107189834 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 166
    4   IGListKit                           0x0000000107848349 -[IGListCollectionViewLayout _calculateLayoutIfNeeded] + 4489
    5   IGListKit                           0x0000000107846ebc -[IGListCollectionViewLayout prepareLayout] + 44
    6   UIKitCore                           0x00000001150ed5a8 -[UICollectionViewData _prepareToLoadData] + 212
    7   UIKitCore                           0x00000001150cc9a2 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 12464
    8   UIKitCore                           0x00000001150d5f24 -[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:] + 71
    9   UIKitCore                           0x00000001150d6267 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 434
    10  UIKitCore                           0x00000001150d6092 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 90
    11  UIKitCore                           0x00000001150d6015 -[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 74
    12  UIKitCore                           0x00000001150d5f6a -[UICollectionView performBatchUpdates:completion:] + 53
    13  IGListKit                           0x0000000107830991 __62-[IGListAdapterUpdater performBatchUpdatesWithCollectionView:]_block_invoke.115 + 481
    14  IGListKit                           0x000000010782f237 -[IGListAdapterUpdater performBatchUpdatesWithCollectionView:] + 5559
    15  IGListKit                           0x0000000107833071 __55-[IGListAdapterUpdater _queueUpdateWithCollectionView:]_block_invoke + 401
    16  libdispatch.dylib                   0x000000010d7ced7f _dispatch_call_block_and_release + 12
    17  libdispatch.dylib                   0x000000010d7cfdb5 _dispatch_client_callout + 8
    18  libdispatch.dylib                   0x000000010d7dd080 _dispatch_main_queue_callback_4CF + 1540
    19  CoreFoundation                      0x000000010c5bda79 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    20  CoreFoundation                      0x000000010c5b8126 __CFRunLoopRun + 2310
    21  CoreFoundation                      0x000000010c5b74d2 CFRunLoopRunSpecific + 626
    22  GraphicsServices                    0x000000010ed632fe GSEventRunModal + 65
    23  UIKitCore                           0x000000011583bfc2 UIApplicationMain + 140
    24  DRC                                 0x000000010302e2fb main + 75
    25  libdyld.dylib                       0x000000010d844541 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Scenario: I've to display two sections in each row where as my collection view leading and trailing is bind to super view. While presenting, the list should have leading and tailing margin.

Question: What is the best way to adding left and right content insets to collection view?

Current working solution:

override func sectionController(_ section: ListBindingSectionController<ListDiffable>,
                                    viewModelsFor object: ListDiffable) -> [ListDiffable] {
        if section.section % 2 == 0 {
            inset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0)
        } else {
            inset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16)
        }

        return [ViewModel(item: object)]
    }

Not sure, Whether this is the correct solution or hack.

DimaVartanian commented 5 years ago

@tarunbhutani any chance you can create a sample project that demonstrates this issue and post a link here so I can take a look?

RamblinWreck77 commented 5 years ago

For what it's worth I'm running into this issue too. My scenario is a bit different though.

A: Portrait collection view/IGListKit B: Landscape collection view/IGListKit

When A does a UIWindow transition -> B B updates the orientation lock and auto rotate spins the view into landscape.

When B dismisses/tells the coordinator to return to A the collection view within A will sometimes throw this error

*** Assertion failure in -[IGListCollectionViewLayout _calculateLayoutIfNeeded](), /Pods/IGListKit/Source/IGListCollectionViewLayout.mm:527
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Width of item 0 in section 0 (414 pt) must be less than or equal to container (392 pt) accounting for section insets {0, 0, 0, 0}'

Whats weird is it only happens ~5-10% of the time, and it's definitely happening while the auto rotate is being executed by the system and viewDidLoad is called inside controller A.

B is setup like this:

override public var shouldAutorotate: Bool {
        switch UIDevice.current.orientation() {
           case .landscapeRight: return false
           default: return true
        }
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeRight
    }

    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeRight
    }

And A has the same but portrait.

hzandi commented 4 years ago

I have the same problem with that assertion our project was written by another programmer so I unlock library and comment this assertion in IGListCollectionViewLayout.mm lines 519-527

I couldn't find which Controller has that problem :|

nodediggity commented 4 years ago

I'm seeing the same issue on the latest release and also building from master directly.

@tarunbhutani / @HamidZandi I don't suppose you were able to get to the bottom of this at all please?

I'm building against iOS 12 through to the latest beta. I can try and find some time to put together an app that replicates this over the next few days.

siimooo commented 3 years ago

Did anyone found solution for this particular issue?

I have the same problem after updated from iOS 13 to 14.

mohpor commented 2 years ago

To anyone that is facing this issue: Please check your sections' func sizeForItem(at index: Int) -> CGSize to see if you are using collectionContext.containerSize.width or something similar. Because containerSize does not take insets into account and will request a size from collection view which will not be available to it (hence, the assertion)!

You can do something like this (in your section):

var cellWidth: CGFloat {
    collectionContext.containerSize.width - (self.inset.left + self.inset.right)
  }

  var cellHeight: CGFloat {
    // calculate your height
  }

  override func sizeForItem(at index: Int) -> CGSize {
    CGSize(width: cellWidth, height: cellHeight)
  }

p.s.: for some reasons unknown to me, collectionContext.insetContainerSize does not work properly or, I'm not using it right.