Info | Value |
-------------------------|-------------------------------------|
Platform | ios
Platform Version | 12.2
SnapKit Version | 5.0.0
Integration Method | cocoapods
After SnapKit update (5.0.0 was 4.2.0) I have now fatal error on updateConstraints
Updated constraint could not find existing matching constraint to update
After some investigations I discovered where the issue is located: LayoutConstraint.swift
The object comparison between firstAnchor or secondAnchor doesn't work properly.
I don't understand the purpose of #574 because firstItem
is unowned(unsafe)
meaning it'll crash if you try to update constraints for deallocated object
The real question is: Why are you trying to update constraints for deallocated objects 😄
The point of the https://github.com/SnapKit/SnapKit/pull/574 is that the object that the constraints are updated for is not deallocated and the EXC_BAD_ACCESS is raised when the firstItem or secondItem are accessed. The problem is fixed with https://github.com/SnapKit/SnapKit/pull/574. Please, follow Apple documentation about this properties:
firstItem.firstAttribute {==,<=,>=} secondItem.secondAttribute * multiplier + constant
Access to these properties is not recommended. Use the `firstAnchor` and `secondAnchor` properties instead.
It is ”not recommended by Apple”, so what? It's not deprecated and I join @arnauddorgans, this version completely broken my projects too, rollback to 4.2 needed.
@bill350 @arnauddorgans I think @sashabelonogov's intentions were good so there's no need to be ill willed about this.
@sashabelonogov I believe the problem is that you're doing a ===
compare which compares the object pointers (invalid since NSLayoutAnchor is unique to each constraint) instead there is a weak var item: AnyObject
inside NSLayoutAnchor
that we can compare which from looks is identical to the old NSLayoutConstraint.item
but weak so a nil value will not cause a crash.
@arnauddorgans @bill350 can either of you two check against develop
and see if this solves your issue?
Sorry @robertjpayne if we were annoyed.
Fixes are always good intentions, but in this case the issue reproductibility was easy.
To avoid that in the future, we can add UI tests target on the SnapKit project ;)
Anyway, according to your reply, there are two things:
develop
fixes not compileI just tried to link the top commit c904582015d5a8eed917d79a7f28ea2b5a8ddde3
on the develop
branch but I've got compile errors on an "item" property for NSLayoutAnchor
🤔. I think something is missing, or maybe you've mixed firstItem
property?
I think the basis of the problem, with the merge of https://github.com/SnapKit/SnapKit/pull/574, is the introduction of the anchor system for the layout constraint comparaison, where NSLayoutAnchor
seems to change after constraint creation.
I understand the Apple documentation that @sashabelonogov mentioned, but it's different things & levels for SnapKit equality comparaison.
Here an example between anchors vs items comparaison on a topMargin
update (from 0
to 30
):
| Anchor pointers comparaison (false) | Items pointers comparaison (true) |
|------|------|
| |
|
Please check the @arnauddorgans sample too.
@bill350 thanks for your help, can you test again with latest commit? Sorry my time is extremely limited (the .item
property is only available on macOS fun times…)
@robertjpayne, no pressure 🤗.
We have to take our time for this issue, with @sashabelonogov and @arnauddorgans too.
Create a dedicated branch will be better, I will find time for a PR tomorrow.
I can still have my project on Swift 5 and point to the 4.2 release of SnapKit in Swift 4.2 ;)
I've checked the commit and I still have a fatal error with the same sample of @arnauddorgans.
I don't understand why you are using anchor objects comparaison instead of items because it will simply not succeed. NSLayoutAnchor
property will be different during the comparaison. Perhaps there is a difference between iOS and macOS layouting?
I've not developed macOS apps so far... I'm waiting for @sashabelonogov details too 🙂.
I will be able to dedicate some time to it to help with the issue.
I have an example that raises EXT_BAD_ACCESS randomly (every second/third time the application is opened) when the items are used (4.2.0 of SnapKit) The application works well with the changes applied in 5.0.0.
@bill350 or @arnauddorgans, does every updateConstraints raise this fatalError?
If not, could you please share an example to help reproduce it?
Thank you!
@sashabelonogov, sure, it fails with margin properties, with topMargin
for instance, but no crash with .top
.
Simply use this sample code to test the crash:
import UIKit
import SnapKit
class ViewController: UIViewController {
let snapView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.snapView)
self.snapView.snp.makeConstraints { (make) in
make.topMargin.equalToSuperview()
}
self.snapView.snp.updateConstraints { (make) in
make.topMargin.equalToSuperview()
}
}
}
Sound like xxMargin (xx: top, left, right, bottom)as a computed property, created every time when accessed it. Using === is not the right way. There is no problem when updating only top, left, right, bottom. Also, it does not work when using as the following way,
self.snapView.snp.makeConstraints { (make) in
make.top.equalTo(self.view.topMargin)
}
self.snapView.snp.updateConstraints { (make) in
make.top.equalTo(self.view.topMargin)
}
Any updates on this regression @sashabelonogov ?
Did you check the sample code?
Has this problem been resolved?
No. We just raised the regression about margins update crash, but no strong investigation started to fix it (simply rollback).
I'm looking into this again today, I'm really sorry for the major delay just been super busy.
This is now resolved with release of 5.0.1, the solution was an entire rollback on #574. @arnauddorgans if you can provide a more concrete example of what is causing this bug we can possibly work towards a fix.
The main issue is that SnapKit has no other way to compare constraints (NSLayoutAnchor is simply just not equatable and does not have public API's suitable for comparing).
My guess is your main issue is caused by you losing references to NSLayoutGuide's or NSLayoutAnchor's and then attempting an update constraint.
v5.0.1 Has this problem been resolved?
Most helpful comment
@sashabelonogov, sure, it fails with margin properties, with
topMargin
for instance, but no crash with.top
.Simply use this sample code to test the crash: