Latest Post

flutter interview questions and answers What is NSURLSession & URL Session and Networking? How to use Swiftui searchable

How to use SwiftUI AsyncImage : Images and videos power almost all contemporary apps and websites. All of the visuals you see on social networking, entertainment, and commerce applications come from a backend source. Since several backend calls are required for this, if you really waited for all of those photos to load before displaying the website, it would take a long time for the applications to load, which would have a negative impact on the user experience.

A fairly straightforward but effective solution to this problem is to load the picture asynchronously and display a placeholder image till that time. Almost all apps that asynchronously load and cache photos follow this identical methodology 

SwiftUI AsyncImage is a new built-in view that SwiftUI 2021 brings. It provides a quick way to download and render a remote image from a URL. At the most fundamental level, if all we needed to do was render a downloaded image exactly as it is, we can now accomplish so as follows:

A built-in view called AsyncImage allows for the asynchronous loading and showing of distant pictures. All you have to do is provide the picture URL. The difficult task of obtaining the distant picture and displaying it on screen is then handled by AsyncImage.

I’ll demonstrate how to use AsyncImage in SwiftUI apps in this article. You need Xcode 13 and iOS 15 in order to follow the lesson.

 AsyncImage(url: URL(string: "https://leadbycode.com/TestImage.jpeg")) // 1       

The fundamentals of an SwiftUI AsyncImage

There are a several initializers included with AsyncImage, the most basic of which accepts an optional URL as an argument. As a result, you don’t need to manually unwrap the URL; instead, AsyncImage will either show the picture if loading was successful or a grey placeholder by default.

Start by adding a copy of SwiftUI AsyncImage to the project you’re working on.

struct ContentView: View {
    var body: some View {
        AsyncImage(url: URL(string: "https://leadbycode.com/TestImage.jpeg"))
    }
}

Using Placeholder views and appropriately altering SwiftUI AsyncImages

SwiftUI AsyncImage has initializers that allow access to the loaded image in order to influence how the picture is shown once it has been loaded. You may utilise the content closure provided by the init(url:scale:content:placeholder) initializer, which accepts an Image instance and produces a View. As a consequence, we may utilise it to add modifiers to the final image. To correctly scale the picture, we may, for instance, add a.resizable or.aspectRatio modifier.

struct ContentView: View {
    var body: some View {
        AsyncImage(url: URL(string: "https://leadbycode.com/TestImage.jpeg"), scale: 3) { image in
            image
              .resizable()
              .aspectRatio(contentMode: .fill)
        } placeholder: {
            Color.blue
        }
            .frame(height: 300)
    }
}

One thing to bear in mind, though, is that the view provided by the placeholder closure is used as a fallback in case an error occurred in addition to being utilised while the picture is being loaded. Again, it could be OK for some use scenarios, but in the example above, we wanted to show a ProgressView while our picture was being loaded. However, if the download failed, we probably don’t want to keep showing the loading spinner.

Fortunately, there is a solution to deal with it as well. We can create a closure that generates the view’s content based on what AsyncImagePhase the download process is currently in by using the third type of initializer that AsyncImage presently ships with.

We may additionally supply a few more arguments, such as the scale we anticipate the downloaded picture to have. However, it doesn’t appear like we can have any influence over the download process itself. There doesn’t appear to be a way to add any more cache layers on top of URLSession’s built-in caching, according to the documentation for AsyncImage, which notes that it will always utilise the app’s default URLSession.shared instance to conduct each network request.

Nevertheless, I believe that SwiftUI AsyncImage is a very welcome addition to SwiftUI’s collection of built-in views and that it will be quite helpful in a variety of applications.

struct ContentView: View {

    var body: some View {
        VStack {
            AsyncImage(url: URL(string: "https://leadbycode.com/TestImage.jpeg")) { phase in
                switch phase {
                case .empty:
                    ProgressView()
                case .success(let image):
                    image.resizable()
                         .aspectRatio(contentMode: .fit)
                         .frame(maxWidth: 300, maxHeight: 100)
                case .failure:
                    Image(systemName: "photo")
                @unknown default:
                    EmptyView()
                }
            }
            ...
        }
    }
}

Animation Added to Transaction for swiftUI AsyncImage

When the phase changes, the same init enables you define an optional transaction. For instance, the code snippet that follows instructs the transaction parameter to utilise a spring animation:

When the image is downloaded in this manner, you will see a fade-in animation. The code won’t function if you test it in the preview window. To view the animation, please be sure to test the code in a simulator.

struct ContentView: View {

    var body: some View {
        VStack {
            AsyncImage(url: URL(string: "https://leadbycode.com/TestImage.jpeg"), transaction: Transaction(animation: .spring())) { phase in
    switch phase {
    case .empty:
        Color.blue.opacity(0.1)
 
    case .success(let image):
        image
            .resizable()
            .aspectFit()
 
    case .failure(_):
                    Image(systemName: "photo")
                    .resizable()
 
    @unknown default:
                    Image(systemName: "photo")
    }
}
.frame(width: 300, height: 500)
.cornerRadius(20)
            }
        }
}