UIImageView
image transition
fade effect
iOS development
Swift programming

Fade/dissolve when changing UIImageView's image

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you assign a new image directly to a UIImageView, the change is immediate and can feel abrupt. The standard UIKit fix is to animate the content swap with a cross-dissolve transition. For this specific task, UIView.transition with .transitionCrossDissolve is usually the simplest and cleanest solution.

The Standard Cross-Dissolve Solution

A minimal implementation looks like this:

swift
1import UIKit
2
3func setImageWithFade(_ imageView: UIImageView, image: UIImage, duration: TimeInterval = 0.25) {
4    UIView.transition(
5        with: imageView,
6        duration: duration,
7        options: .transitionCrossDissolve,
8        animations: {
9            imageView.image = image
10        },
11        completion: nil
12    )
13}

This cross-dissolves from the old image to the new one without requiring a custom animation layer.

Why UIView.transition Fits the Problem

UIView.transition is designed for view-content changes. You provide:

  • the target view
  • a duration
  • a transition style
  • the state change to animate

For an image swap, the state change is just assigning a new image. That keeps the code short and readable.

Reusable Extension

If your app performs this pattern often, wrap it in an extension.

swift
1import UIKit
2
3extension UIImageView {
4    func setImage(_ image: UIImage?, animated duration: TimeInterval = 0.25) {
5        UIView.transition(
6            with: self,
7            duration: duration,
8            options: .transitionCrossDissolve,
9            animations: {
10                self.image = image
11            },
12            completion: nil
13        )
14    }
15}

Usage becomes simple:

swift
imageView.setImage(UIImage(named: "photo2"), animated: 0.3)

That centralizes the animation behavior instead of repeating it in every view controller.

Async Image Loading Still Needs Main-Thread UI Updates

If the image comes from the network or disk, prepare it first and then perform the animated assignment on the main queue.

swift
1DispatchQueue.global().async {
2    let data = try? Data(contentsOf: url)
3    let image = data.flatMap(UIImage.init)
4
5    DispatchQueue.main.async {
6        imageView.setImage(image, animated: 0.25)
7    }
8}

The animation itself is a UI operation, so it belongs on the main thread.

Keep Heavy Work Out of the Animation Block

The transition block should only perform the state change you want animated. Do not fetch data, decode large assets, or do other heavy work inside it.

A good sequence is:

  1. load the image first
  2. switch to the main queue
  3. animate only the image assignment

That keeps the dissolve effect smooth and predictable.

Consider Reuse and Flicker in Fast-Scrolling Views

In table views and collection views, images may change frequently as cells are reused. In those cases, fading every update can sometimes look noisy or reveal stale-image flashes if the old request finishes late.

A common practical rule is:

  • fade intentional content swaps the user is meant to notice
  • be more careful with rapidly reused cells fed by asynchronous image loaders

Pick a Sensible Duration

A very short fade can feel like no animation at all, while a very long fade makes the interface feel sluggish. In practice, a duration around 0.2 to 0.35 seconds is a reasonable starting point for ordinary image replacement.

Common Pitfalls

The biggest mistake is updating the image from a background thread when the source was loaded asynchronously.

Another mistake is putting expensive work inside the animation block, which can cause stuttering.

A third issue is applying the fade indiscriminately in reused scrolling cells without considering flicker or stale-image races.

Summary

  • Use UIView.transition with .transitionCrossDissolve to fade between UIImageView images
  • Keep the animation block limited to assigning the new image
  • Wrap the behavior in an extension if the pattern appears often
  • Load remote images first, then animate the UI update on the main thread
  • Use the effect deliberately in reused views so the transition improves UX instead of adding visual noise

Course illustration
Course illustration

All Rights Reserved.