I'm noticing at various times throughout my app that when I call UIView.animateWithDuration, if I have any other kind of auto-layout requests, or even something as simple as changing the constant of an NSLayoutConstraint, those changes will also be animated even when they are NOT inside the animation block. For example: I have a UIViewController that right after viewDidAppear is called, will add an image which was chosen by the user to a UIScrollView so that it can be resized and edited. I'm working on adding a little demonstration view with some GIF's to help the user when they first use the app. Once the view shows, it should add the image (I've set it to fit to their screen at first) to the scrollView, and then animate the demonstrationView alpha from zero to 1.0. The problem I'm experiencing, is even though my function to add and resize the image assignImageChosen is called before animateWithDuration, and is outside the animation block, the changes in size constraints are also animated.
override func viewDidAppear(animated: Bool) {
if let image = startImage {
self.assignImageChosen(image)
currentlyEditing = true
}
if preLoadGame {
UIView.animateWithDuration(1.0, delay: 0.5, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
self.demonstrationView.alpha = 1.0
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Here is the function assignImageChosen:
func assignImageChosen(image: UIImage) {
var ratio:CGFloat!
let screen:CGFloat = max(self.scrollView.frame.height, self.scrollView.frame.width)
var maxImage:CGFloat!
if UIDevice.currentDevice().orientation.isPortrait {
if image.size.height >= image.size.width {
maxImage = max(image.size.height, image.size.width)
}
else {
maxImage = min(image.size.height, image.size.width)
}
}
else {
if image.size.width >= image.size.height {
maxImage = max(image.size.height, image.size.width)
}
else {
maxImage = min(image.size.height, image.size.width)
}
}
if maxImage > screen {
ratio = screen/maxImage
}
else {
ratio = 1.0
}
self.imageView.image = image
self.imageHeight.constant = image.size.height * ratio
self.scrollView.contentSize.height = image.size.height * ratio
self.imageWidth.constant = image.size.width * ratio
self.scrollView.contentSize.width = image.size.width * ratio
}
The variables imageHeight and imageWidth are both NSLayoutConstraint's, and imageView is the UIImageView to which they are set. So once I change the image, I change the constraints so that the imageView inside the UIScrollView is fit to the screen. The problem is that when I do it like this, even though the changes are called outside the animation block, those changes are still animated.
Here's a GIF example of what I'm trying (poorly) to communicate through words:
I have found a way to circumvent this issue, but it feels like a complete hack. I manually code the system to delay the execution of the animation by using the dispatch_after command like so:
override func viewDidAppear(animated: Bool) {
if let image = startImage {
self.assignImageChosen(image)
currentlyEditing = true
}
if preLoadGame {
let delay = 0.5 * Double(NSEC_PER_SEC)
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(popTime, dispatch_get_main_queue(), {
UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
self.demonstrationView.alpha = 1.0
self.view.layoutIfNeeded()
}, completion: nil)
})
}
}
So instead of using the delay variable inside the animateWithDuration function, I instead delay the execution of the function. It works, but I would think there must be a better way to do this! Why are those layout changes being animated when they aren't inside the animation block? How can I get around this in a proper, efficient manner?
Here is how it looks with my hack, and how I would imagine it should look without it:
I appreciate any help with this frustrating issue!

