UIImageView
image transition
fade effect
SwiftUI
iOS development

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

Changing a UIImageView image abruptly can feel jarring, especially when the user expects content to update smoothly. The usual iOS fix is a cross-dissolve transition, which fades the old image out while the new image fades in.

The good news is that this effect is simple with UIKit. The more important part is knowing when to animate directly on the image view and when asynchronous image loading or caching needs extra coordination.

Use UIView.transition

For local images or already-available UIImage objects, the standard pattern is UIView.transition:

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

This is the most direct answer for a dissolve effect. It uses a built-in transition and keeps the code small.

Update from a View Controller

A typical usage might look like this:

swift
1class PhotoViewController: UIViewController {
2    @IBOutlet weak var imageView: UIImageView!
3
4    @IBAction func nextTapped(_ sender: UIButton) {
5        let newImage = UIImage(named: "landscape-2")!
6        setImageWithFade(imageView, image: newImage)
7    }
8}

As long as the image is already in memory or bundled with the app, this usually behaves exactly as expected.

Fade After Asynchronous Image Loading

If the image arrives from the network, make sure the UI update happens on the main thread and only after the image has finished loading:

swift
1func loadImage(url: URL, into imageView: UIImageView) {
2    URLSession.shared.dataTask(with: url) { data, _, _ in
3        guard let data, let image = UIImage(data: data) else {
4            return
5        }
6
7        DispatchQueue.main.async {
8            UIView.transition(with: imageView,
9                              duration: 0.3,
10                              options: .transitionCrossDissolve,
11                              animations: {
12                                  imageView.image = image
13                              },
14                              completion: nil)
15        }
16    }.resume()
17}

This keeps the transition smooth even when the source image is remote.

Avoid Animating Placeholder Noise

If images are loading repeatedly in fast-scrolling interfaces such as table or collection views, not every update should animate. Repeated fades can make the UI feel noisy.

A common pattern is:

  • show placeholders without animation
  • fade only when a real image replaces an existing real image
  • cancel outdated requests when cells are reused

That keeps the dissolve effect meaningful instead of distracting.

Choose Duration Conservatively

Cross-dissolve animations usually work best when they are short. Durations around 0.2 to 0.35 seconds often feel smooth without making the interface sluggish.

If the animation is too slow, the app can feel unresponsive. If it is too fast, the user may not perceive the transition at all.

Use Animation Only When It Adds Meaning

A fade transition is most effective when the user benefits from noticing that one image replaced another. If images change constantly or very rapidly, a dissolve on every update can make the interface feel busy instead of polished.

Common Pitfalls

  • Setting imageView.image directly and expecting an automatic fade.
  • Updating the image from a background thread after an async download.
  • Animating every image change in a scrolling list and creating visual noise.
  • Using a duration so long that the image transition feels laggy.
  • Confusing UIKit UIImageView animation with SwiftUI image transitions, which use a different API style.

Summary

  • Use UIView.transition with .transitionCrossDissolve for a simple fade effect.
  • This works best when the new image is ready to assign.
  • For network images, update the UIImageView on the main thread after loading completes.
  • Keep fade durations short and deliberate.
  • In high-frequency UI updates, animate selectively instead of on every image change.

Course illustration
Course illustration

All Rights Reserved.