UIView Block-Animation Completion Always True - swift

I have had an animation that I have recently caught to be not working
//time is a variable used in my code
UIView.animate(withDuration: time, delay: 0, options: [.curveLinear, .allowUserInteraction], animations: {
//this class is ofType UIScrollView
self.setContentOffset(CGPoint(x: self.contentSize.width-self.frame.width, y: 0), animated: false)
//Completion Handler
}, completion: { finished in
//It's always true, not sure a way to fix this
if(finished ) {
But, later in my code, I have a method to remove certain animations, specifically from this scrollView.
self.layer.removeAllAnimations()
It gets called, and I would assume it is suppose to make the above
if(finished ) { //Here
return false, therefore it should not go inside the finished. But, finished is ALWAYS true. Whether I cancel this animation, continue the animation, doesn't matter what I do to the animation, the completion handler is always true. Any tips on this matter?

Your call to setContentOffset specifies animated:false, if that is the only property you are changing, then there are no actual animations going on, so the call to .animate(...) will always complete with a value of true. If you set this property (or another one) with animated:true and your duration is too short for the animation to finish, then it could complete with a false value for the parameter.

Related

UIView.animate() issue

I have a code, where UI elements are changed after user interaction. I use UIView.animate() to refresh UI. The code is pretty simple:
UIView.animate(withDuration: 1.0) {
self.fadeIn()
} completion: { _ in
UIView.animate(withDuration: 1.0) {
self.fadeOut()
}
}
Very important point is that total animation duration from beginning to the end should be 2 seconds. But sometimes, there are no UI changes in fadeIn(), and UIView.animate() just get immediately to completion block. But in that option I want to have a delay for duration time (1 sec), and only after that get to completion block to fadeOut. How I can force animate with duration even if it's nothing to animate in animation block? Thanks in advance!
Maybe don't call fadeOut() in the completion block, and just make sure that it's called with one second delay after the fadeIn() is called?
UIView.animate(withDuration: 1.0) {
self.fadeIn()
}
UIView.animate(withDuration: 1.0, delay: 1.0) {
self.fadeOut()
}

How to perform action on RealityKit animation completion

In WWDC19 talk they showed how to animate Entity and perform action on animation completion (go to minute 12 for reference) like this:
let animationController = move(to: flipUpTransform, relativeTo: parent, duration: 0.25, timingFunction: .easeInOut)
animationController.completionHandler {
// Perform some action
}
But it looks like that they removed or never added this completionHandler. Instead they have isCompleted boolean property.
I am new to swift so I have no idea to use this isCompleted to perform some actions upon animation completion. How can I solve this?
The documentation says:
Look for one of the events in AnimationEvents if you want to be alerted when certain aspects of animation occur.
So you can use Combine to get notified when the animation finishes. so
let animation = entity.move(to: targetTransform, relativeTo: nil, duration: 1)
arView.scene.publisher(for: AnimationEvents.PlaybackCompleted.self)
.filter { $0.playbackController == animation }
.sink(receiveValue: { event in
/ * your completion handler */
}).store(in: &subscriptions)

Pre-Emptive Swift Animation Object Move - Confusing

Good day,
I have a very simple animation function, that drops a button by 200.
However, I discover that before the animation begins, the object is moved up (-) by 200! Therefore, after the animation, the button is back where it started.
I tried to set self.button1.center = self.view.center in viewDidAppear before calling the function.
func dropStep(){
UIView.animate(withDuration: 6, animations: {
self.button1.center.y += 200
}, completion: nil)
}
I expected the animation to start from where it is intended (at the center of the view) and not pre-emptively shifted up by 200 points.
Try,
func dropStep(){
button1.center = self.view.center
UIView.animate(withDuration: 6, animations: {
self.button1.center.y += 200
}, completion: nil)
}
Okay, so I could not genuinely find the reason behind this.
However, this was an app that was used and reused to learn animations, so maybe somehow the object referencing outlets or some sort of hidden reference was messed up, such that the app behaved funny.
Therefore, I created a new app with virtually the same code, and it behaved as expected. Thanks anyway for your help.

Stopping and Resetting a CGAffineTransform

I'm trying to write code where when a trigger happens an instance of UIImageView creates a slow "growing" effect with a CGAffineTransform running for 20 seconds.
The issue happens when the trigger happens again before the first transform has completed. Instead of the image resetting back to it's original size, it shrinks exponentially, depending on when the trigger happened during the first transformation.
Here is my current code:
func changeCategoryImage() {
self.categoryPanoramaImageView.transform = CGAffineTransform.identity
UIView.transition(with: self.categoryPanoramaImageView, duration: 0.4, options: .transitionCrossDissolve, animations: {
self.categoryPanoramaImageView.image = self.newPanoramaImage
}) { (done) in
UIView.animate(withDuration: 10, animations: {
self.categoryPanoramaImageView.transform = CGAffineTransform(scaleX: 5.0, y: 5.0)
})
}
}
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
How can I halt and reset the current running transformation in order to start a new one?
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
Correct. It isn't the case. That's not how animations work. You are making a direct change to the underlying view (i.e. the model layer), but the animation is still present (i.e. the presentation layer).
Thus, you are setting the view's transform to the identity, but you are not removing the existing animation. And animations are additive by default. Hence the result you are observing.
Try inserting
self.categoryPanoramaImageView.layer.removeAllAnimations()
as the first line of your function. That way, you will remove the animation and start over from the identity.

Implementing basic animations with tvOS

I'm hoping someone may be able to help me understand why my tvOS animations are not running.
In my code I have a function like this:
func testAnimation() {
clockLabel.alpha = 0.0
UIView.animateWithDuration(1.0, animations: {
self.clockLabel.alpha = 1.0
})
}
I am calling testAnimation() from within my viewDidLoad(), but no animation ever seems to happen.
I've tested with a few different types of animations, from things like position to opacity, but it seems that no animation ever actually runs in the Simulator.
At this time, my app does not have a focus. All I'm trying to do is load a blank UIView with a label in the middle that fades in.
You're trying to animate your UILabel before it has been displayed. Move your animation from viewDidLoad() to viewDidAppear().
I can confirm this behaviour as this happens for me as well. What I did was setting a delay of 0.1 (afterDelay:), and it is "good enough"
On the other hand, what DID actually work was setting a transform for my views. E.g. (objc though):
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.5,0.5);
[UIView animateWithDuration: 0.5 animations:^{
_myView.transform = scaleTransform;
} completion: nil]
Maybe it's a bug in tvOS
Try using UIView Animation, like this (Swift):
clockLabel.alpha = 0
UIView.animateWithDuration(0.5, delay: 0.0, options: .Linear, animations: {
self.clockLabel.alpha = 1.0
}, completion: { finished in
// you may add some code here to make another action right after the animation end, or just delete this comment :)
})
This works on our side.