# swiftui-cached-async-image and the one-line fix for a repeat download

> CachedAsyncImage is a drop-in replacement for SwiftUI's AsyncImage that adds URLCache-backed caching, keeping the same API and behaviour so switching costs one word. The limit is that it is a narrow wrapper rather than an image pipeline, and the README makes no claim about disk behaviour, memory pressure or prefetching.

**lorenzofiamingo/swiftui-cached-async-image** — CachedAsyncImage is the simplest way to add cache to your AsyncImage.

- Repository: https://github.com/lorenzofiamingo/swiftui-cached-async-image
- Stars: 711 · Forks: 83
- Language: Swift
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/lorenzofiamingo-swiftui-cached-async-image

## A drop-in replacement, and that is the whole pitch

CachedAsyncImage is described as AsyncImage, but with cache capabilities, and the README states that it has the exact same API and behavior as AsyncImage.

That claim is what makes the library small in one sense and useful in another. The migration is a single word:

```swift
AsyncImage(url: logoURL)
```

becomes

```swift
CachedAsyncImage(url: logoURL)
```

For a team already shipping SwiftUI with AsyncImage, this is the lowest-friction change in the category. There is no wrapper type, no configuration object to thread through the view hierarchy, and no new phase to reason about in the view body. Whatever your code does with AsyncImage's phase and result, it keeps doing.

The alternative approach would be to introduce an image loading library with its own model, its own error type and its own cache configuration, and then rewrite every call site. The trade is that you get a lot more machinery in exchange. This library declines that trade, and the question for an adopter is whether you need the machinery.

The audience is a SwiftUI developer who has noticed the same image being fetched again on every view reappearance and wants that specific problem solved without restructuring the app.

## Two extra initializers: custom cache and URLRequest

Beyond the AsyncImage initializers, the README describes two additions.

The first is choosing the cache. By default URLCache.shared is used, and you can point the view at a different one:

```swift
CachedAsyncImage(urlRequest: logoURLRequest, urlCache: .imageCache)
```

The second is the ability to use a URLRequest instead of a URL, which is what makes custom headers, cache policies and timeouts reachable at all. With AsyncImage taking only a URL, you have no way to attach a request configuration; with a URLRequest you do.

The custom cache in the example is an extension on URLCache with a large memory capacity and a very large disk capacity:

```swift
extension URLCache {
    
    static let imageCache = URLCache(memoryCapacity: 512_000_000, diskCapacity: 10_000_000_000)
}
```

Those numbers are the point of the example. URLCache.shared has modest defaults, and an app that loads a lot of images will hit them, so a dedicated cache with a bigger memory and disk allowance is the mechanism for avoiding repeated fetches. The extension approach is also the idiomatic way to do it, since URLCache is a class you instantiate rather than something you configure.

The cost of a custom cache is that it is a separate store. Anything you put in imageCache is not in URLCache.shared, so if some other part of your app loads the same URL through the shared cache, you get two copies and two fetches.

## The five percent rule that will bite your image sizes

The README includes one operational warning that is worth reading twice, because it is the sort of constraint that produces a bug report months later.

When setting a cache, the response, in this case the image, must be no larger than about five percent of the disk cache. The README links to Apple's discussion of this rule.

Applied to the example cache, that is roughly 500 megabytes of disk capacity for a ten gigabyte cache, so a single image must be comfortably under that. That is fine for photographs served at thumbnail sizes and a problem for large downloads, and there is no documented way in the library to opt out of the rule for one oversized asset, because the library is not doing the caching itself, URLCache is.

This is the practical reason the shared cache and a custom cache are not interchangeable. URLCache.shared has its own disk capacity, and if your images are large relative to it, the same rule applies with a smaller number, and the symptom is that images do not appear to cache at all, because the response is written and then evicted.

If you are loading full resolution images, the fix is to serve resized images from the server, not to enlarge the cache. The library cannot help here, and the README does not pretend otherwise.

## Installing through the Swift Package Manager in Xcode

Installation is the standard Xcode package flow, with three steps.

Open your project in Xcode and navigate to File, Swift Packages, Add Package Dependency. Paste the repository URL, which is https://github.com/lorenzofiamingo/swiftui-cached-async-image, and click Next. Click Finish.

There is no CocoaPods or Carthage instruction, and no build-flag setup. The repository is a Swift package: it has a Package.swift at the root, a Package.resolved, a Sources directory, and a .spi.yml file, which is the configuration for the Swift Package Index. The presence of Package.resolved means the resolved dependency graph is committed, so the version your project builds against is recorded rather than floating.

The main branch is the default branch, and the released versions are 2.1.2 from 2026-05-01, 2.1.1 from 2022-06-09 and 2.1.0 from 2022-03-09.

That release history deserves a note. The gap between 2.1.1 in 2022 and 2.1.2 in 2026 is four years, and the repository is not archived, with the last push on 2026-07-01. A library this small can sit untouched for years and then take a release to accommodate a new Swift or SwiftUI version, so the version number tells you very little about how often the code changes. What it does tell you is that 2.1.2 is recent enough to have been made against a current toolchain.

## What the library does not do, and the case for a fuller pipeline

The absence of features is the most useful thing to evaluate here, because a caching wrapper is easy to mistake for an image loading library.

There is no documented cache invalidation API. You cannot ask the library to drop a cached image when the underlying resource changes, so a changed image at the same URL stays stale until the cache entry expires or is evicted. There is no documented prefetching, so a table of thumbnails that scrolls to the cell before it becomes visible still shows an empty placeholder on first appearance. There is no documented cancellation, no retry policy, and no documented support for a progress indicator during download, all of which you would need for anything beyond a static list.

If your app needs those, the alternative is a full image loading library, which is a different category of dependency with a caching layer, request management and its own configuration surface. The difference in approach is that such a library owns the loading pipeline and exposes it to you, whereas CachedAsyncImage delegates the work to URLCache and exposes a SwiftUI view.

The deciding question is therefore narrow. If the problem is repeated downloads of the same URLs and nothing else, this library solves it in one word. If the problem is a controlled image pipeline with invalidation, progress and prefetch, it is the wrong size of tool, and the reason it is so small is the same reason it cannot do those things.

## Conclusion

swiftui-cached-async-image is a good fit for a SwiftUI app whose image lists redownload the same URLs on every appearance, because swapping AsyncImage for CachedAsyncImage keeps the initializers and behaviour identical and adds caching without a new architecture. It is a poor fit if you need more than caching, since there is no documented support for request cancellation, cache invalidation on demand, disk limits or prefetching. Before adopting, check that the images you load are small enough for the disk cache, since the README warns that a response must be no larger than about five percent of the disk cache, and decide whether URLCache.shared is enough or whether you need the custom URLCache extension, and note that the last release was 2.1.2 on 2026-05-01 with the last push on 2026-07-01.

## FAQ

### How do I install swiftui-cached-async-image?

In Xcode, open your project, go to File, Swift Packages, Add Package Dependency, paste https://github.com/lorenzofiamingo/swiftui-cached-async-image, click Next and then Finish. It is distributed as a Swift package.

### How is CachedAsyncImage different from AsyncImage?

The README states that CachedAsyncImage has the exact same API and behavior as AsyncImage, so you swap AsyncImage for CachedAsyncImage. It adds the option to specify the cache, where URLCache.shared is used by default, and to use a URLRequest instead of a URL.

### How do I give CachedAsyncImage a larger cache?

Extend URLCache with a static instance, for example static let imageCache = URLCache(memoryCapacity: 512_000_000, diskCapacity: 10_000_000_000), and pass it as the urlCache argument. The README warns that the response must be no larger than about five percent of the disk cache.

### When was the last version of swiftui-cached-async-image released?

Version 2.1.2 was released on 2026-05-01, after 2.1.1 from 2022-06-09 and 2.1.0 from 2022-03-09. The repository is not archived and the last push was on 2026-07-01.

## Sources

- [Issues](https://github.com/lorenzofiamingo/swiftui-cached-async-image/issues)
- [License: MIT](https://github.com/lorenzofiamingo/swiftui-cached-async-image/blob/main/LICENSE)
- [lorenzofiamingo/swiftui-cached-async-image on GitHub](https://github.com/lorenzofiamingo/swiftui-cached-async-image)
- [README](https://github.com/lorenzofiamingo/swiftui-cached-async-image/blob/main/README.md)
- [Releases](https://github.com/lorenzofiamingo/swiftui-cached-async-image/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lorenzofiamingo-swiftui-cached-async-image
