How do I animate a set of UIImages backward inside UIImageVIew – swift – programmatically

I suggest we override the startAnimating() method. This way we can provide our own logic of the animation and decide what the next frame should be.

We’ll create a frameTimer that will replace the image of the UIImageView every equal fraction of the animationDuration. It’ll iterate over the images array forwards and backwards until stopped with the stopAnimating() method.

class BoomerangImageView: UIImageView {
    // MARK: Overrides
    override func startAnimating() {
        guard let frames = animationImages, frames.count > 1 else {
            return
        }
        image = frames.first
        
        let timePerFrame = animationDuration / Double(frames.count)
        let timer = Timer(fire: Date(timeIntervalSinceNow: timePerFrame),
                          interval: timePerFrame,
                          repeats: true) { [weak self] _ in
            self?.changeFrame()
        }
        RunLoop.current.add(timer, forMode: .common)
        frameTimer = timer
    }
    
    override func stopAnimating() {
        frameTimer?.invalidate()
        frameTimer = nil
        currentFrameIndex = 0
    }
    
    // MARK: Private
    private var frameTimer: Timer?
    private var isAnimatingForward = true
    
    private var currentFrameIndex = 0 {
        didSet {
            if let frames = animationImages,
               currentFrameIndex >= 0,
               currentFrameIndex < frames.count {
                image = frames[currentFrameIndex]
            }
        }
    }
    
    private func changeFrame() {
        guard let frames = animationImages, frames.count > 1 else {
            stopAnimating()
            return
        }
        
        let canAnimateForward = currentFrameIndex < frames.count - 1
        let canAnimateBackward = currentFrameIndex > 0
        isAnimatingForward = (isAnimatingForward && canAnimateForward) || (!isAnimatingForward && !canAnimateBackward)
        currentFrameIndex += isAnimatingForward ? 1 : -1
    }
}

Then in your view controller, you run the animation just like you planned:

class ViewController: UIViewController {
    @IBOutlet weak var imageView: BoomerangImageView!
    
    let frames: [UIImage] = [
        // your images here
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        imageView.animationImages = frames
        imageView.animationDuration = 2
        imageView.startAnimating()
    }
}

It should look something like this:

boomerang demo

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top