How to Do Imageview.Startanimating() with Completion in Swift

how to do imageView.startAnimating() with completion in swift?

Add #selector() and @objc at last solution.

When the button is pressed you can call a function with a delay:

self.perform(#selector(afterAnimation), with: nil, afterDelay: imageView1.animationDuration)

Then stop the animation and add the last image of imageArray to the imageView in the afterAnimation function:

@objc func afterAnimation() {
imageView1.stopAnimating()
imageView1.image = imageArray.last
}

UIImageView with completion handler

Please try the following:

// Create a Core Animation transaction and set its completion block
CATransaction.begin()
CATransaction.setCompletionBlock {
NSLog("Animation complete")
}

// create your animations as before
iv.animationImages = (0...40).map { UIImage(named: "loader_\($0)")! }
iv.animationDuration = 40 / 30
iv.animationRepeatCount = 1
iv.image = UIImage(named: "loader_40")
iv.startAnimating()

// Commit the transaction
CATransaction.commit()

Wrapping inside a Core Animation transaction should provide a completion block that will get called when the animation is complete.

Access Method After UIImageView Animation Finish

Use performSelector:withObject:afterDelay::

[self performSelector:@selector(animationDidFinish:) withObject:nil
afterDelay:instructions.animationDuration];

or use dispatch_after:

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, instructions.animationDuration * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self animationDidFinish];
});

How to use completion block for UIView.animate()?

The size is 0, 0. Transforming zero by any scale is still zero. I would advise you to not use transform at all, but rather just set the final frame to be what you want.

E.g.,

let startFrame = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
let endFrame = view.bounds

let imageView = UIImageView(image: ...)
imageView.contentMode = .scaleAspectFill
view.addSubview(imageView)
imageView.frame = startFrame
UIView.animate(withDuration: 3, delay: 0, options: .curveEaseInOut) {
imageView.frame = endFrame
} completion: { _ in
// do something here
}

That yields:

Sample Image


By the way, the performSegue probably should be inside a completion closure of the inner animate call.

How to animate the change of image in an UIImageView?

I am not sure if you can animate UIViews with fade effect as it seems all supported view transitions are defined in UIViewAnimationTransition enumeration. Fading effect can be achieved using CoreAnimation. Sample example for this approach:

#import <QuartzCore/QuartzCore.h>
...
imageView.image = [UIImage imageNamed:(i % 2) ? @"3.jpg" : @"4.jpg"];

CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;

[imageView.layer addAnimation:transition forKey:nil];

Navigate to New View Controller after Animation is Completed in Swift 3.0

Use DispatchQueue.main.asyncAfter.

EDITED

Set Storyboard ID to SecondViewController.

Sample Image

Example #1:

...
imageView.animationRepeatCount = 1 // <-- here
imageView.startAnimating()

DispatchQueue.main.asyncAfter(deadline: .now() + imageView.animationDuration) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
self.show(secondViewController, sender: nil)
}

Example #2:

...
imageView.animationRepeatCount = 1 // <-- here
imageView.startAnimating()
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
self.show(secondViewController, sender: nil)
}

stop UIImageView.transition

In the completion handler, you call self.animateImage() again to form a loop. If you call this conditionally on isAnimating, then the loop will "break" once isAnimating is false:

completion: { _ [weak self] in
guard let `self` = self else { return }
if self.nextImage != self.imagesCount - 1 {
self.nextImage += 1
} else {
self.nextImage = 0
}
// notice this condition
if self.isAnimating {
self.animateImage()
}
}

Also note that imageView.startAnimating() starts animating using the imageView.animationImages, not the animation you have created here with UIImageView.animate, which is just the same as UIView.animate. So you only need the single line of

isAnimating.toggle()

in tapOnImage.

Since you seem to want to restart the animation when isAnimating is set to true, you should call animateImage in its didSet:

private var isAnimating = true {
didSet {
if isAnimating {
animateImage()
}
}
}


Related Topics



Leave a reply



Submit