| Info | Value |
| --- | --- |
| Platform | ios |
| Platform Version | 10.0 |
| SnapKit Version | 3.0.1 |
| Integration Method | cocoapods |
| SnapKit version | Broken |
| --- | --- |
| 0.22.0 | false |
| 3.0.1 | true |
| view | frame |
| --- | --- |
| titleLabel | (15.0, 45.0, 345.0, 86.5) |
| subtitleLabel | (15.0, 65.0, 345.0, 18.0) |
| self | (-187.5, -49.0, 375.0, 98.0) |
subtitleLabel.x must be 146.5 (20.0 + 5.0 + 20.0 + 86.5 + 15.0)
self.height must be 179.5 (146.5 + 18.0 + 15.0)
self.x must be -179.5
self.y must be -20
func initialize() {
self.snp.makeConstraints { (make) in
let superview = self.superview!
make.top.equalTo(superview.snp.top)
make.left.equalTo(superview.snp.left)
make.right.equalTo(superview.snp.right)
}
// Title Label
let _titleLabel = UILabel(frame: CGRect.zero)
_titleLabel.numberOfLines = 0
_titleLabel.textColor = UIColor.white
_titleLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)
self.addSubview(_titleLabel)
_titleLabel.snp.makeConstraints { (make) in
let superview = _titleLabel.superview!
make.top.equalTo(superview.snp.top).inset(statusBarHeight + 5 + 20)
make.left.equalTo(superview.snp.left).inset(15)
make.right.equalTo(superview.snp.right).inset(15)
}
titleLabel = _titleLabel
// Subtitle Label
let _subtitleLabel = UILabel(frame: CGRect.zero)
_subtitleLabel.numberOfLines = 0
_subtitleLabel.textColor = UIColor.white
_subtitleLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
self.addSubview(_subtitleLabel)
_subtitleLabel.snp.makeConstraints { (make) in
let superview = _subtitleLabel.superview!
make.top.equalTo(_titleLabel.snp.top).inset(20)
make.left.equalTo(superview.snp.left).inset(15)
make.right.equalTo(superview.snp.right).inset(15)
make.bottom.equalTo(superview.snp.bottom).inset(15)
}
subtitleLabel = _subtitleLabel
}
func dismiss() {
// Hide with animation
UIView.animate(withDuration: 1.3, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 1.0, options: [], animations: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.snp.updateConstraints({ (make) in
let superview = strongSelf.superview!
make.top.equalTo(superview.snp.top).inset(-strongSelf.frame.height)
strongSelf.layoutIfNeeded()
})
}, completion: { [weak self] (finished) in
guard let strongSelf = self else { return }
strongSelf.removeFromSuperview()
})
}
func show() {
// Initial hidden
self.snp.updateConstraints { (make) in
let superview = self.superview!
make.top.equalTo(superview.snp.top).inset(-self.frame.height)
layoutIfNeeded()
// Output
print(self.titleLabel.frame)
print(self.subtitleLabel.frame)
print(self.frame)
}
// Show with animation
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 1.0, options: [], animations: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.snp.updateConstraints({ (make) in
let superview = strongSelf.superview!
make.top.equalTo(superview.snp.top).inset(-20)
strongSelf.layoutIfNeeded()
})
}, completion: { [weak self] (finished) in
// ...
})
// Dismiss after 2 seconds
let delayTime = DispatchTime.now(withDelay: 2.0) // DispatchTime extension
DispatchQueue.main.asyncAfter(deadline: delayTime) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.dismiss()
}
}
@cooler333 can you try to simplify your example a bit to confirm this?
Something like this on dismiss:
// Initial hidden
self.snp.updateConstraints { (make) in
let superview = self.superview!
make.top.equalTo(superview.snp.top).offset(500)
}
UIView.animate(withDuration: 0.5) { self.layoutIfNeeded(); self.superview.layoutIfNeeded() }
And see if anything happens? It's hard to follow such a complex code example without the full source to diagnose.
First guess is you may need to call self.superview.layoutIfNeeded()
as well as self.layoutIfNeeded()
.
Also if you call layoutIfNeeded()
inside a SnapKit constraint maker closure UIKit will not yet have the newly created constraints, you need to call layoutIfNeeded
AFTER the constraint maker closure is finished.
layoutIfNeeded()
superview?.layoutIfNeeded()
This helps! fixed it.
but in iOS 9 + swift 2.3 have different behaviour. very strange. Thank You!
@cooler333 sometimes the internals of iOS change a bit, as a rule of thumb you need to call layoutIfNeeded()
on the closest common superview of the two views the constraint is from and to.
So for self -> self.label
you need to call it on self.superview
Example project
recently upgraded to SnapKit 3, found updateConstraints doesn't work consistently: similar to @cooler333 show/hide animation case, but my issue is updating constraints seems to work only for the first time, then updating won't take any effect. same codebase upgrade from Swift 2, didn't change a line. now it's broken
Most helpful comment
@cooler333 sometimes the internals of iOS change a bit, as a rule of thumb you need to call
layoutIfNeeded()
on the closest common superview of the two views the constraint is from and to.So for
self -> self.label
you need to call it onself.superview