CachedAsyncImage is the simplest way to add cache to your AsyncImage.

Last update: May 22, 2022

SwiftUI CachedAsyncImage πŸ—ƒοΈ

CachedAsyncImage is AsyncImage, but with cache capabilities.

Usage

CachedAsyncImage has the exact same API and behavior as AsyncImage, so you just have to change this:

AsyncImage(url: logoURL)

to this:

CachedAsyncImage(url: logoURL)

In addition to AsyncImage initializers, you have the possibilities to specify the cache you want to use (by default URLCache.shared is used), and to use URLRequest instead of URL:

CachedAsyncImage(urlRequest: logoURLRequest, urlCache: .imageCache)
// URLCache+imageCache.swift

extension URLCache {
    
    static let imageCache = URLCache(memoryCapacity: 512*1000*1000, diskCapacity: 10*1000*1000*1000)
}

Remember when setting the cache the response (in this case our image) must be no larger than about 5% of the disk cache (See this discussion).

Installation

  1. In Xcode, open your project and navigate to File β†’ Swift Packages β†’ Add Package Dependency...
  2. Paste the repository URL (https://github.com/lorenzofiamingo/swiftui-cached-async-image) and click Next.
  3. Click Finish.

Other projects

SwiftUI MapItemPicker πŸ—ΊοΈ

SwiftUI PhotosPicker πŸŒ‡

SwiftUI VerticalTabView πŸ”

SwiftUI SharedObject 🍱

GitHub

https://github.com/lorenzofiamingo/swiftui-cached-async-image
Comments
  • 1. URLCache returns nothing before restart

    Thanks for the library. I try to use it in a scroll view with transaction animation when an image is loaded:

    CachedAsyncImage(
        url: imageURL,
        urlCache: .imageCache,
        transaction: Transaction(animation: .default)
    ) { phase in
        switch phase {
        case .empty:
            ProgressView()
                .frame(height: 100)
        case .success(let image):
            image
                  .resizable()
        case .failure:
            Image(systemName: "wifi.slash")
        @unknown default:
            EmptyView()
        }
    }
    .frame(maxHeight: 200)
    
    private extension URLCache {
        static let imageCache = URLCache(
            memoryCapacity: 512 * 1000 * 1000,
            diskCapacity: 10 * 1000 * 1000 * 1000
        )
    }
    
    

    But once an image is loaded it continues to animate cell appearance (and other View content) when scrolling down and up again. URLCache doesn't return anything before the app relaunch.

    Reviewed by denis-obukhov at 2022-02-07 12:29
  • 2. transaction: Transaction(animation: .easeInOut) does not appear to work

    Great job on this! I was having a huge problem with AsyncImage redownloading images in lazy stacks that this lib completely eliminates.

    The one difference I noticed is that transaction animations don't appear to work. I had a nice ease animation with AsyncImage that does not trigger when I swap it with CachedAsyncImage. Here's my body

    var body: some View { GeometryReader { geo in AsyncImage( url: url, transaction: Transaction(animation: .easeInOut) ) { phase in switch phase { case .empty: Rectangle() .fill(Color.gray1) case let .success(image): image.resizable() .scaledToFill() case .failure: Rectangle() .fill(Color.gray1) @unknown default: EmptyView() } } .frame(width: geo.size.width, height: geo.size.height) .clipped() } } }

    Reviewed by recurrence at 2021-10-30 21:34
  • 3. Is 404 counted as an error?

    It seems after I switched from AsyncImage to your CachedAsyncImage, 404 is no longer an error. Thus when the code tried to load an URL that returned 404, the code would never reach phase.error, thus a placeholder is always showing.

    Reviewed by livid at 2021-11-21 12:07
  • 4. Use provided transition on cache hit

    When provided with an URL that ends up being redirected (301), no cache hit occurs during initialization, as URLCache.cachedResponse expects the redirected URL to be provided instead. This leads to _phase being set to .empty, even though the ensuing .load call will result in a cache hit, because URLSession.data does behave properly.

    ... that's my theory, at least 😬

    I saw, that f24cfe71158f428e9a396a19335221f0fe19e10e did away with animating on cache hit. What was the reason for that change?

    Reviewed by PhilipTrauner at 2022-03-04 15:03
  • 5. "EMPTY" printed on empty image state

    There is a print statement here that I don't think should be included because having no URL is a valid state and the print doesn't seem to have any purpose. The current inclusion of the statement spams my console since I use this library to asynchronously load a list of users.

    I'd personally like to see it removed or at least have it made toggleable so I don't have to see it.

    As of 3/1/22 the master branch has this issue.

    Reviewed by ImTheSquid at 2022-03-01 22:35
  • 6. Transaction doesn't work

    Good work, thanks, Lorenzo! Im using library to fetch and cache images like this:

           CachedAsyncImage(
            url: URL(string: path),
            urlCache: .imageCache,
            transaction: Transaction(animation: .easeInOut)) { phase in
                
                switch phase {
                case .empty:
                    ProgressView()
                        .progressViewStyle(.circular)
                case .success(let image):
                    image
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                case .failure:
                    Image("")
                @unknown default:
                    Image("")
                }
            }
            .frame(
                width: frameForBaseImage().0,
                height: frameForBaseImage().1
            )
            .cornerRadius(filesGroupingSelection == .yearGrouping ? 4 : 8)
    

    But transaction doesn't work at all(

    Reviewed by polkandra at 2022-04-28 15:54
  • 7. Question - Where in the code does caching occur?

    First off, amazing work! Thanks πŸ™

    I was debugging an issue I have with images no caching correctly (likely due to size or cookies?) and it got me going through the code.

    Could you point me to where the caching occurs? I only see one storeCachedResponse that in my case never gets triggered because there aren't any redirects.

    Does the session automatically do it in this line: let (data, _, metrics) = try await session.data(for: request)? I was under the likely incorrect impression we had to explicitly call storeCachedResponse.

    Reviewed by alfonsogarza at 2022-04-24 23:59
  • 8. Question - Is an in-memory cache?

    I mean, will the image still be cached after I exit and re-enter the app, or is just while the app is "alive"? For example I open the app today, and then I open it again in the next month, will the image be still cached?

    Thank you!

    Reviewed by sebasira at 2022-04-06 21:05
  • 9. Archive Failing

    Whenever I archive with your SPM it fails. I was doing a little reading into the matter, and it seems that you're missing some things in your Package.swift file that is causing the problem.

    platforms: [ .iOS(.v15) ],

    Reviewed by hobbesthetige at 2021-11-20 13:09
ZImageCropper is a simplest way to crop image to any shapes you like.
ZImageCropper is a simplest way to crop image to any shapes you like.

ZImageCropper ZImageCropper is a simplest way to crop image to any shapes you like. Example To run the example project, clone the repo, and run pod in

May 15, 2022
A simplest & base on protocol & swifty way to browse photo or video with hero animation.
A simplest & base on protocol & swifty way to browse photo or video with hero animation.

JFHeroBrowser Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation JFHe

May 21, 2022
AsyncImageExample An example project for AsyncImage. Loading images in SwiftUI article.
AsyncImageExample An example project for AsyncImage. Loading images in SwiftUI article.

AsyncImageExample An example project for AsyncImage. Loading images in SwiftUI article. Note: The project works in Xcode 13.0 beta (13A5154h).

Dec 31, 2021
Backport of SwiftUI.AsyncImage to iOS 14, macOS 11, tvOS 14 and watchOS 7 and earlier.

SBPAsyncImage Backport of SwiftUI.AsyncImage to iOS 14, macOS 11, tvOS 14 and watchOS 7 and earlier. AsyncImage is a view that asynchronously loads an

May 6, 2022
A simple and flexible way to add source of overlapping circular pictures, currently supports horizontal overlapping or distant pictures with great layout flexibility.
A simple and flexible way to add source of overlapping circular pictures, currently supports horizontal overlapping or distant pictures with great layout flexibility.

THIS PROJECT IS NO LONGER MAINTAINED. STILL ONE ONLY BEST UI SOLUTION FOR UIKIT DEVELOPERS. SOON WILL COME UP WITH SWIFTUI STILL CONTRIBUTORS ARE WELC

May 9, 2022
A lightweight generic cache for iOS written in Swift with extra love for images.
A lightweight generic cache for iOS written in Swift with extra love for images.

Haneke is a lightweight generic cache for iOS and tvOS written in Swift 4. It's designed to be super-simple to use. Here's how you would initalize a J

May 11, 2022
πŸš€SwiftUI Image downloader with performant LRU mem/disk cache.
πŸš€SwiftUI Image downloader with performant LRU mem/disk cache.

Progressive concurrent image downloader for SwiftUI, with neat API and performant LRU mem/disk cache.

Feb 4, 2022
Asynchronous image downloader with cache support as a UIImageView category
Asynchronous image downloader with cache support as a UIImageView category

This library provides an async image downloader with cache support. For convenience, we added categories for UI elements like UIImageView, UIButton, M

May 22, 2022
DGImageView - Asynchronous image downloader with cache. Supports gif too

DGImageView Installation Usage DGImageView Asynchronous image downloader with cache. Supports gif, memory cache, disk cache features. Installation Xco

Jan 1, 2022
WhiteAndFluffyTest - Scroll images and add them to your favourites via image page
WhiteAndFluffyTest - Scroll images and add them to your favourites via image page

Image service application Scroll images and add them to your favourites via imag

Feb 4, 2022
add text(multiple line support) to imageView, edit, rotate or resize them as you want, then render the text on image
add text(multiple line support) to imageView, edit, rotate or resize them as you want, then render the text on image

StickerTextView is an subclass of UIImageView. You can add multiple text to it, edit, rotate, resize the text as you want with one finger, then render the text on Image.

Apr 18, 2022
TextDrawer, is a UIView allows you to add text, with gesture, on UIView, or UIImage
TextDrawer, is a UIView allows you to add text, with gesture, on UIView, or UIImage

TextDrawer TextDrawer, is a UIView allows you to add text, with gesture, on UIView, or UIImage. About Annotating Images TextDrawer is the easiest way

Mar 5, 2022
A Xcode plugin to add highlight to the instances of selected symbol.
A Xcode plugin to add highlight to the instances of selected symbol.

Auto Highlight Symbol About Xcode 8 Xcode 8 does't support plugins anymore, but there is a workaround, use at your own risk. Xcode can highlight insta

Mar 20, 2022
Shows your photo library grouped by events, to easily export them to your computer
Shows your photo library grouped by events, to easily export them to your computer

Groupir Shows your photo library grouped by events, to easily export them to your computer Features Currently supported features: reading your photo l

Dec 15, 2021
πŸ“Έ A wrapper for AVCaptureSession - The way easier to use the Camera.

Capturer A wrapper for AVCaptureSession - The way easier to use the Camera. Setting up let captureBody = CaptureBody( configuration: .init { $0.

Apr 23, 2022
URLImage is a package that holds an easy way of showing images from an URL.
URLImage is a package that holds an easy way of showing images from an URL.

URLImage Overview URLImage is a package that holds an easy way of showing images from an URL. Usually this processes should take the following process

Nov 1, 2021
A better way to operate QR Code in Swift, support iOS, macOS, watchOS and tvOS.
A better way to operate QR Code in Swift, support iOS, macOS, watchOS and tvOS.

EFQRCode is a lightweight, pure-Swift library for generating stylized QRCode images with watermark or icon, and for recognizing QRCode from images, in

May 12, 2022
A powerful new way to Reddit on iOS.

Slide for Reddit Slide is a powerful open-source, ad-free, Swift-based Reddit browser for iOS. Feel free to join us on the official subreddit for disc

May 17, 2022
Lightbox is a convenient and easy to use image viewer for your iOS app
Lightbox is a convenient and easy to use image viewer for your iOS app

Lightbox is a convenient and easy to use image viewer for your iOS app, packed with all the features you expect: Paginated image slideshow. V

May 9, 2022