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.
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:
For image-heavy apps, the difference was noticeable.
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.
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.URLCache.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 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 |
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.
URLRequestAlthough 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:
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.
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.
URLSessionAnother 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.
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.
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:
If none of these apply, the default implementation is likely the best choice.
Although the API changes are relatively small, the performance improvements can be significant.
Benefits include:
Users may not consciously notice the change, but they'll experience smoother scrolling and images that appear instantly when revisiting previously viewed content.
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.
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:
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.
Apple Documentation:
https://developer.apple.com/documentation/swiftui/asyncimage
WWDC 2026 Session:
https://developer.apple.com/videos/play/wwdc2026/269/?time=1198
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.