IGListKit icon indicating copy to clipboard operation
IGListKit copied to clipboard

App crash whenever adding left/right contentInset in UICollectionView.

Open tarunbhutani opened this issue 5 years ago • 6 comments

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.

tarunbhutani avatar Sep 03 '19 03:09 tarunbhutani

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

DimaVartanian avatar Sep 16 '19 16:09 DimaVartanian

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.

RamblinWreck77 avatar Sep 23 '19 14:09 RamblinWreck77

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

hzandi avatar Feb 06 '20 20:02 hzandi

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.

nodediggity avatar Mar 31 '20 15:03 nodediggity

Did anyone found solution for this particular issue?

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

siimooo avatar Jan 22 '21 07:01 siimooo

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.

mohpor avatar Dec 18 '21 22:12 mohpor