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 on NSLayoutConstraint.autoSetPriority #208

Open
pappalar opened this issue Feb 7, 2018 · 6 comments
Open

Crash on NSLayoutConstraint.autoSetPriority #208

pappalar opened this issue Feb 7, 2018 · 6 comments

Comments

@pappalar
Copy link

pappalar commented Feb 7, 2018

Hello,

using NSLayoutConstraint.autoSetPriority(.init(rawValue: 900)) {}
to setup some constrains with a specific priority makes the application crash if the constrains are set on a CollectionView.

Remving the autoSetPriority makes the app stop crashing

*** First throw call stack:
(
	0   CoreFoundation                      0x00000001151bb12b __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x000000011375ff41 objc_exception_throw + 48
	2   CoreFoundation                      0x00000001151c02f2 +[NSException raise:format:arguments:] + 98
	3   Foundation                          0x000000010f212d69 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
	4   UIKit                               0x0000000111666202 __45-[UICollectionViewData validateLayoutInRect:]_block_invoke + 1932
	5   UIKit                               0x00000001116654f1 -[UICollectionViewData validateLayoutInRect:] + 2964
	6   UIKit                               0x00000001115f9bb9 -[UICollectionView layoutSubviews] + 260
	7   UIKit                               0x0000000110beda6d -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
	8   QuartzCore                          0x00000001102bf61c -[CALayer layoutSublayers] + 159
	9   QuartzCore                          0x00000001102c37ad _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
	10  UIKit                               0x0000000110bd77ca -[UIView(Hierarchy) layoutBelowIfNeeded] + 662
	11  UIKit                               0x0000000110bdec60 +[UIView(Animation) performWithoutAnimation:] + 90
	12  UIKit                               0x0000000110c7d6e2 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1384
	13  UIKit                               0x0000000110c7da2a -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
	14  UIKit                               0x0000000110c431f6 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3031
	15  UIKit                               0x0000000110c652e6 -[UITableView layoutSubviews] + 176
	16  UIKit                               0x0000000110beda6d -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
	17  QuartzCore                          0x00000001102bf61c -[CALayer layoutSublayers] + 159
	18  QuartzCore                          0x00000001102c37ad _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
	19  QuartzCore                          0x000000011024a86c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 364
	20  QuartzCore                          0x0000000110277946 _ZN2CA11Transaction6commitEv + 500
	21  QuartzCore                          0x00000001101c43cc _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 960
	22  QuartzCore                          0x0000000110304894 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 248
	23  CoreFoundation                      0x000000011514a899 __CFMachPortPerform + 169
	24  CoreFoundation                      0x000000011514a7d9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
	25  CoreFoundation                      0x000000011514a741 __CFRunLoopDoSource1 + 465
	26  CoreFoundation                      0x0000000115142524 __CFRunLoopRun + 2596
	27  CoreFoundation                      0x0000000115141889 CFRunLoopRunSpecific + 409
	28  GraphicsServices                    0x000000011a89b9c6 GSEventRunModal + 62
	29  UIKit                               0x0000000110b1c5d6 UIApplicationMain + 159
	30  x                              0x0000000109edeb2f main + 111
	31  libdyld.dylib                       0x00000001181edd81 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
@toohotz
Copy link
Member

toohotz commented Feb 22, 2018

Could you show us an example of where you're trying to set the priority of the constraint on the UICollectionView?

@pappalar
Copy link
Author

pappalar commented Feb 22, 2018

I have too many layers to paste the whole thing so I am going to explain:

I have a UITableViewCell that contains a UIStackView
inside the stackView there are some UIViews called Containers that are used to hide or show the content inside them.

Stackview
    -> Container1
        -> View1 <= this might be a collection view, and that crashes the app
        -> View2
    -> Container2
        -> View3
    -> Container3
        -> View4

in the initializer of those views (View1, 2, 3, 4 etc..) I have the autoSetDimension so that it is called only once at initialization of the view, and then it reused

So ideally

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

dequeues a cell for the first time, hence initializing it.
Calls the initializer for each View inside the stack view and calls autoSetDimension

Now note that I am setting priority 900.
There is a specific reason for that.

I am using the Containers to hide multiple Views at the same time, by setting container1.isHidden = true.
Being inside a stackview, this applies automatically a heightConstrain of constant 0 and priority 1000 in order to hide them

The priority of 900 is made on purpose so that the stackView is free to add and remove these constrains without conflicting with the views internal constrains, but having a priority of them (and hiding/showing them correctly without triggering warnings)

This works fine most of the time, and I get no warning for unstatisfaiable constrains in console.

However this crashes the app, if the autoSetDimension method is called on a collectionView.

Some of the views I showed above (View1 for example) is a horizontal collectionView that is used to make a carousel in the table view cell.

Setting the vertical dimension of the collection view crashes the app with the stacktrace above

@toohotz
Copy link
Member

toohotz commented Feb 22, 2018

Understandable at what you're trying to achieve as it makes sense. Taking a look at the stack trace, an exception is being thrown at the -[UICollectionViewData validateLayoutInRect:] so there might be a chance that where you're applying the height constraint may require you to invalidate the flow layout of the collection view (collectionView.collectionViewFlowLayout.invalidateLayout()). My assumption is that the collapsing from the stack view is causing layout issues with the UICollectionView.

@pappalar
Copy link
Author

Yes, that is correct.
I am now calling invalidateLayout() on the collectionViews in the prepareForReuse of each tableViewCell.

I had however had to remove PureLayout constrains else the crash was still happening.

Without the autoSetDimension the crashes are not there, but I have a million warning due to StackView fighting to have height = 0 @1000 and intrinsicContentSize pushing for a random number @1000

That is why I was wondering if wrapping the constrains of PureLayout into a autoSetPriority
was creating some delayed blocks rendered in the layout engine and triggering a wrong layout

@toohotz
Copy link
Member

toohotz commented Feb 22, 2018

When calls are made through the +[ NSLayoutConstraint autoSetPriority], the ALConstraintsBlock that handles them ensures that the current thread is the main thread so the layouts should be happening serially but clearly there's a rendering issue occurring that you pointed out. When I get some time, I'm going to try and make a sample project to mimic this setup and see if I can play around with it to find out where in the PL code this might be happening. Thanks for pointing this out. 👍🏾

@pappalar
Copy link
Author

Cool! Thanks! I am sorry I cannot provide the code, but it is a company one.
And I didn't have the time to setup a demo proj!

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

No branches or pull requests

2 participants