Tried to use isSkeletonable on a view laid out by auto-layout
The view would render in the auto-layout calculated position with shimmer
The view did not show up
OR
If I set a background color, it shows up as background color, but no shimmer
100% reproducible
let fakeText = UIView()
view.addSubview(fakeText)
fakeText.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: fakeText, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: CGFloat(16)).isActive = true
NSLayoutConstraint(item: fakeText, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: CGFloat(16)).isActive = true
NSLayoutConstraint(item: fakeText, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: CGFloat(16)).isActive = true
// Trying to let autolayout determine the width the component does not render with a shimmer
// NSLayoutConstraint(item: fakeText, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 1, constant: -CGFloat(16)).isActive = true
// Setting the width statically it will render
NSLayoutConstraint(item: fakeText, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: CGFloat(200)).isActive = true
// If I set a background color, the component will render in the expected position with red background in the width relationship case.
// This demonstrates it as not an auto-layout issue.
// In the static width case, setting background has no effect.
fakeText.backgroundColor = UIColor.red
fakeText.isSkeletonable = true
SkeletonView version: 1.4.2
Xcode version: 10.1
Swift version: 4.2
Wasn't able to upload a PR, but this diff reproduces the issue with the sample project. I could not reproduce it using Autolayout from storyboard, only from programatic autolayout.
zipped a mov showing what I describe
bug.mov.zip
Modifying this code in ViewController worked around the issue. To my surprise it needed both to clear skeleton on didAppear and updateConstraints.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
refreshSkeleton()
}
override func updateViewConstraints() {
super.updateViewConstraints()
refreshSkeleton()
}
This work around also succeeded inside of my app. Wary of going into the underlying nest of code blind to figure out the race condition causing this.
I'm having the same issue. Any result about it?
@bpollock-vida What does your refreshSkeleton look like?
@bpollock-vida What does your
refreshSkeletonlook like?
I think it's this code:
app loads without label
make a skeleton change
self.view.hideSkeleton() is called
the next show of the skeleton correctly renders the label
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I am also facing this issue.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Has this been fixed yet?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Still waiting for fix
@whoyawn @JMCPH I found refreshSkeleton in our code:
func refreshSkeleton() {
removeSkeleton()
let gradient = SkeletonGradient(baseColor: UIColor(hexString: "EEEEEE"), secondaryColor: UIColor(hexString: "F9F9F9"))
showAnimatedGradientSkeleton(usingGradient: gradient)
}
func removeSkeleton() {
hideSkeleton()
stopSkeletonAnimation()
recursiveSubview { (subview) in
subview.removeSkeleton()
}
}
and the recursive stuff
/// Apply a closure on all subviews using breadth first traversal
func recursiveSubview( apply: (inout UIView) -> Void) {
var queue = [UIView]()
while queue.isNotEmpty {
var focus = queue.removeFirst()
apply(&focus)
queue = queue + focus.subviews
}
}
/// Apply a closure to all superviews of a view
func recursiveSuperview( apply: (inout UIView) -> Void) {
var parent: UIView? = superview
while parent != nil {
guard var focus = parent else { break }
apply(&focus)
parent = focus.superview
}
}
(recursiveSuperview is used by a Skeletonize() helper method)
Most helpful comment
I am also facing this issue.