How to display images from the web using AsyncImage

Each WWDC brings lots of new goods for all Apple ecosystem developers. The 2021 edition wasn’t different. AsyncImage view is a new SwiftUI addition that expects a URL instead of an asset to display images. Read further to learn how to use it.

Displaying images from the web is a widespread task in mobile applications. You can see this in all social media applications, web-based knowledge bases, or apps that stream files from servers. It requires more work than displaying images locally. After all, we have to wait until the image is loaded (usually displaying a placeholder) and handle situations where the network connection is not reliable (or the file doesn’t exist anymore). AsyncView is created to make those operations easier. When it comes to displaying images, it uses an Image view underneath.

The simplest form of AsyncView requires only the url parameter with the URL object. This url parameter is optional, so you don’t have to check its existence when creating it using the URL(string:_) constructor.

let url = URL(string: "http://placekitten.com/200/200")
AsyncImage(url: url)

But often, you may want to do more with a result. One of the most common scenarios was to resize the image to fit its frame. The AsyncImage first initializer can handle scale parameter and two convenient closures - content and placeholder. The first one performs operations on the Image view when it is finally loaded, and the second one returns a view displayed when an image is loading.

AsyncImage(url: url) { image in
    image.resizable()
} placeholder: {
    Text("Loading...")
}

With content closure, you can resize the image, fit it to content or apply rounded corners.

But there is a second initializer that allows for more advanced control. You will probably be using that version more often. It also supports url and scale properties, but there is a new transaction parameter and content closure gets AsyncImagePhase enum. You can use the data provided in that enum to return a view for different phases of image loading. When the network file is loaded (success phase), you will get an Image view. For failure error is returned. There is a third empty phase, which means that the file is being loaded. The transaction parameter is used to provide an animation that is applied when phases change.

AsyncImage(
    url: url,
    transaction: Transaction(
        animation: .easeInOut
    )
) { phase in
     if let image = phase.image {
         image.resizable()
    } else if phase.error != nil {
        Text("Error!")
    } else {
        Text("Loading...")
    }
}
AsyncImage SwiftUI Playground