AsyncImage Finally Gets Caching in SwiftUI

August 1, 2026

For years, AsyncImage has been one of the easiest ways to display remote images in SwiftUI. With just a URL, SwiftUI handled downloading and displaying images without requiring any third party libraries.

However, there was one major limitation.

If an image disappeared from the screen, for example while scrolling through a List or LazyVStack and later became visible again, AsyncImage downloaded the image again instead of reusing it from memory.

This behavior wasn't ideal for feeds, galleries, or any image heavy interface.

Starting with XCode 27, that changes.

AsyncImage now supports standard HTTP caching out of the box. Images are automatically cached according to the server's cache headers, and most apps benefit from this improvement without changing a single line of code.

Let's explore what has changed and how you can customize the new behavior.


Why AsyncImage Needed Caching

Imagine you're building an app that displays hundreds of remote images.

struct PetRow: View {
    let pet: Pet

    var body: some View {
        AsyncImage(url: pet.imageURL)
    }
}

When users scroll down, images are downloaded and displayed.

When they scroll back up, older versions of AsyncImage would often fetch those same images again.

Although networking layers might cache data on disk in some situations, AsyncImage itself didn't keep previously displayed images readily available in memory for immediate reuse. This could lead to:

  • unnecessary network requests
  • additional decoding work
  • slower scrolling back through long lists
  • extra bandwidth usage

For image-heavy apps, the difference was noticeable.


What's New in WWDC 2026

Apple has significantly improved AsyncImage.

Beginning with the 2027 platform releases, AsyncImage automatically supports standard HTTP caching.

That means downloaded images are now cached according to the HTTP response headers provided by your server.

The best part?

You don't need to change any code.

Your existing implementation continues to work.

AsyncImage(url: imageURL)

Now when users scroll away and back again, cached images can appear immediately instead of triggering another download.


How Automatic HTTP Caching Works

The new behavior follows normal HTTP caching rules instead of introducing a custom SwiftUI specific cache.

The process looks like this:

  • AsyncImage downloads an image.
  • The server returns cache headers.
  • The response is stored in URLCache.
  • The next request checks the cache.
  • If the cached response is still valid, the image is loaded directly from the cache.

Because this uses standard HTTP caching, your app automatically benefits from server-side caching policies.

This also means the server remains in control of how long images should stay cached.


Before vs After

Before WWDC 2026 After WWDC 2026
Images often reloaded when appearing again Images are reused from cache whenever possible
More network requests Fewer network requests
More image decoding Better scrolling performance
Higher bandwidth usage Reduced bandwidth
No configuration Automatic

Existing Code Gets Faster Automatically

If you're already using AsyncImage, you don't need to migrate anything.

For example:

struct PetView: View {
    let pet: Pet

    var body: some View {
        AsyncImage(url: pet.imageURL) { image in
            image
                .resizable()
                .scaledToFill()
        } placeholder: {
            ProgressView()
        }
    }
}

That's it.

When built with Xcode 27, image caching happens automatically.


Customizing Image Downloads with URLRequest

Although automatic caching is sufficient for many apps, sometimes you need finer control over how requests are made.

iOS 27 introduces a new initializer that accepts a URLRequest.

Instead of passing only a URL, you can now customize the request itself.

AsyncImage(
    request: URLRequest(
        url: pet.imageURL,
        cachePolicy: .returnCacheDataElseLoad
    )
)

This unlocks many possibilities, including:

  • choosing a cache policy
  • adding HTTP headers
  • setting authentication tokens
  • configuring request timeout
  • using conditional requests

The cache policy shown above tells the system to return cached data whenever possible before downloading the resource again.

This is particularly useful when images change infrequently.


Understanding Cache Policies

Using a URLRequest allows you to select the caching behavior that best fits your application.

For example:

let request = URLRequest(
    url: imageURL,
    cachePolicy: .reloadIgnoringLocalCacheData
)

Always downloads the latest image.

Or:

let request = URLRequest(
    url: imageURL,
    cachePolicy: .returnCacheDataElseLoad
)

Uses cached data first and only downloads when necessary.

Choosing the appropriate policy depends on how frequently your images change.

For profile pictures or product images, caching is usually desirable.

For frequently updated dashboards or live camera snapshots, always downloading may be more appropriate.


Using a Custom URLSession

Another major addition is the ability to provide your own URLSession.

Previously, AsyncImage always used the system managed session.

Now you can configure your own networking behavior.

Apple demonstrated the following example during WWDC.

@Observable
class StickerStore {
    static let imageSession: URLSession = {
        let configuration = URLSessionConfiguration.default

        configuration.urlCache = URLCache(
            memoryCapacity: 64 * 1024 * 1024,
            diskCapacity: 256 * 1024 * 1024
        )

        return URLSession(configuration: configuration)
    }()
}

Here, a custom URLCache increases both memory and disk cache capacity.

This can improve performance in apps displaying many large images.

Applying the Custom Session

Once the session has been created, use the new asyncImageURLSession modifier.

ForEach(pets) { pet in
    AsyncImage(
        request: URLRequest(
            url: pet.imageURL,
            cachePolicy: .returnCacheDataElseLoad
        )
    )
}
.asyncImageURLSession(StickerStore.imageSession)

Every AsyncImage inside the view hierarchy now uses the supplied URLSession.

This approach keeps networking configuration centralized while allowing every image request to benefit from the customized cache.


When Should You Use a Custom URLSession?

Most applications do not need to create a custom session.

The default behavior is designed to work well for typical apps.

Consider providing your own URLSession when you need to:

  • increase cache size for image heavy applications
  • customize networking behavior
  • use different request configurations
  • isolate image downloads from the rest of your networking stack
  • share a dedicated image cache across specific screens

If none of these apply, the default implementation is likely the best choice.


Performance Benefits

Although the API changes are relatively small, the performance improvements can be significant.

Benefits include:

  • Faster scrolling through image lists
  • Reduced network traffic
  • Lower battery usage
  • Fewer repeated image downloads
  • Better user experience on slower networks
  • Less image decoding work

Users may not consciously notice the change, but they'll experience smoother scrolling and images that appear instantly when revisiting previously viewed content.


Server Caching Still Matters

One important detail is that AsyncImage now follows standard HTTP caching rules.

This means the effectiveness of caching depends on your server configuration.

If your image server sends appropriate cache headers, SwiftUI can reuse cached images efficiently.

If caching headers are missing or explicitly disable caching, AsyncImage will respect those instructions and may still perform network requests.

In other words, the client and server work together to achieve the best caching behavior.


Should You Replace Third-Party Image Libraries?

Many SwiftUI developers rely on libraries such as Kingfisher, Nuke, or SDWebImageSwiftUI because they provide advanced image loading and caching features.

With automatic HTTP caching now built into AsyncImage, many simpler use cases no longer require an external dependency.

However, third-party libraries still offer capabilities beyond the scope of AsyncImage, including:

  • progressive image loading
  • animated GIF and WebP support
  • advanced image processing
  • prefetching
  • retry strategies
  • custom cache management
  • placeholder transitions

If your app only needs to display remote images efficiently, the enhanced AsyncImage may now be all you need. For more advanced image pipelines, dedicated libraries remain valuable.

References

Apple Documentation:

https://developer.apple.com/documentation/swiftui/asyncimage

WWDC 2026 Session:

https://developer.apple.com/videos/play/wwdc2026/269/?time=1198


Final Thoughts

AsyncImage has evolved into a much more capable remote image solution.

By adding automatic HTTP caching, SwiftUI eliminates one of the most common performance complaints developers had with the original API. Existing applications immediately benefit from fewer network requests and smoother scrolling, all without requiring code changes.

For developers who need additional control, the new URLRequest initializer and asyncImageURLSession modifier provide flexible ways to customize caching behavior and networking configuration while continuing to use SwiftUI's simple declarative API.

If you've avoided AsyncImage because of its previous caching limitations, WWDC 2026 is a great time to take another look.

Thank you for reading. If you have any questions feel free to follow me on X and send me a DM. If this article helped you, Buy me a coffee.