In this SwiftUI tutorial, we will learn how to load and display an image asynchronously from the Internet.
Note that the SwiftUI's AsyncImage view uses the shared URL Session instance to load an image from
a specified URL and then display it on the screen. Until the remote image loads,
the view displays either a standard or a custom-built placeholder.
To gain more control over the loading process,
we can use the initializer, which takes a content closure that receives an Async Image Phase to
indicate the state of the loading operation.
By doing that, we can control what to display on the screen.
In a nutshell, we can return a view that's appropriate for the current phase, such as success, failure, or empty phase.
Alright!
Without further ado, let's create a new project in Xcode and start coding.
Basics.
The simplest way to use Async Image is by specifying the image URL.
To do that, first, we need to create a new property that will store the web address of the image in a string.
Enter this code:
Private. Let. Image URL. String. Equals. https://credo.academy/credo-academy@3x.png.
After that, we will replace the default Text view with the simplest form of Async Image like this:
New comment, Mark, first basic.
Then enter this code: Async Image. URL. URL. String. Image URL.
With this short and quite straightforward piece of code, we can download and display a remote image.
The first thing you can notice on the Preview is a gray placeholder.
The reason behind it is since the euro is optional, therefore the async image will show a default grey
The reason behind it is since the URL is optional. Therefore, the Async Image will show a default gray placeholder if the URL string is invalid.
And if the image can't be loaded for some reason, for example, if the user is offline or the image doesn't exist, then the system will continue showing the same
placeholder image.
That's said, let's see what will happen when we start the Live Preview.
There it goes!
Once the remote image is completely downloaded, Async Image displays this image in its original size.
You know, I uploaded this huge image to the server for you on purpose so I can show you how
to scale it down.
The scale parameter. To make it happen, first comment out this line of code and start a new section by
by entering this code.
New comment, Mark second.
Scale.
Async Image. URL. URL. String. Image URL. Scale. Three, point, zero.
And, that's it! We can see the whole image and not only part of it.
If we want to make the image smaller or larger, then we need to pass a scaling value to the scale parameter like this.
The default value is always 1.0.
The greater the value is, the smaller the image is.
That's why the 2.0 and the 3.0 will scale down the image.
Conversely, a value less than one will make the image bigger.
Let's try to change the scale value from 3.0 to 2.0 and let's see what will happen, shall we?
As you can see, the image scaled up a little bit.
Now let's check out the remote image with the default 1.0 before scaling back to the ideal size.
From now, working with different image sizes shouldn't be hard since you know how this works.
Custom placeholder.
Alright. Now let's jump to the Async Image's next feature, shall we?
Async Image provides another constructor for developers if we need further customization.
Comment out the previous line and enter the following code.
New comment, Mark, third placeholder. AsyncImage, URL, URL, string, image URL.
Image.
In.
Image, placeholder image.
System name, photo.circle.fill.
Padding: 40.
As you can see, we have just added a tiny icon as a placeholder for this async image.
Now with this initializer, we can also use the content and the placeholder parameters to manipulate
the loaded image.
For example, we can add some modifiers to make either the remote image or the placeholder resizable.
Let's do it right now.
Enter the following code:
Image. Resizable. Scaled To Fit.
Then add these new modifiers for the placeholder as well.
Image. Resizable. Scaled To Fit. Frame maximum with.
128. Foreground color purple opacity, zero point five.
And there is a customized placeholder.
What do you think about it?
It's pretty obvious that our own implementation for the placeholder is much better than a blank gray
sheet.
However, we must keep in mind one important thing about these modifiers.
We can not apply image-specific modifiers, like Resizable, directly to an AsyncImage.
Instead, we must apply them to the Image instance that our content or placeholder closures get when
defining the view's appearance.
So far, we covered how to create a basic Async Image, and then we scaled it appropriately.
Finally, we learned how to add a custom placeholder for it.
We discovered a lot, but not everything.
Since there is still one more thing that we should learn about the Async Image.
Image extension.
But before we continue developing this mini application, we should hold on a second and look at our
recent code.
As you can notice, we added many modifiers for the image.
And since we will create a new async image, therefore we need to repeat this code, which is not so
fun after a while, to be honest.
But not only that, there are already some duplicated modifiers in this code as well.
It would much better if we could optimize these modifiers somehow.
And that's what we will do by creating a reusable Image extension.
First of all, select the image's modifiers and cut them out to the clipboard.
After that, we need to navigate the cursor outside the scope of the Content View.
Scroll to the top and enter the following code!
Extension image.
Func image modifier.
Some of you.
Self.
Here we need to paste the modifiers from the clipboard, as I show you. So far, so good.
Now we will continue with creating another function for the placeholder's modifiers.
Enter this code.
Func.
Icon modifier some view.
Self.
Image modifier. Please notice that we have just embedded the previous modifiers into this new one.
How cool is the Swift language?
After all this, we need to cut and paste the remaining modifiers in the placeholder into this image extension.
So let's do it!
Now it's time to add all the necessary image modifiers to the image and placeholder again.
Image, image modifier.
Then jump to the placeholder and add this one to it.
Image icon modifier.
Nothing changed in the Preview, which means that our code works as it should do.
However, our code is much cleaner now, not to mention that we can use the image extension over and over again.
Async image phase. Now the fun part begins!
Select all code in the third section and comment out as I show you.
Then let's create a new section for the Async Image Phase.
Enter. New comment, Mark. Fourth. Phase.
Then we need to create a new Async Image with a different constructor.
Start coding.
Async Image. URL. URL. String.
Image URL. Phase. In.
To gain more control over the loading process, we need to use this new initializer, which takes a content
closure that receives an Async Image Phase to indicate the state of the loading operation.
Also, we should take into consideration that this will return a view that's appropriate for the current
phase.
And these are the phases
Success. The image was successfully loaded.
Failure! The image failed to load with an error.
And finally, the Empty phase, when no image is loaded.
Now, let's see in action how we can work with these Async Image Phases, shall we?
Enter the following code!
Image equals.
Phase dot, image, image, dot, image modifier.
Or else, if.
Phase dot era not equals to No.
Image.
System name and dot circle, dot fill icon modifier.
Else.
Image.
System name, photo, dot circle, dot, film icon modifier.
Padding 40.
As you can see, the Async Image view provides another constructor if we want to take more control of the asynchronous operation.
That's being said, we can display different images in each distinguished phase, such as the success
phase, then the failure phase, and finally the empty stage.
But enough with the talk, and let's see how this works by using
the Live Preview.
After starting the live Preview, we can see the remote image replacing the placeholder image.
So far, nothing new here.
But this will change once we modify the image's URL. So that way, the app could not load the remote image anymore.
For example, we can remove a letter at the end of the string, and voila!
By refreshing the live Preview, the URL session's new response will be a failure.
That's said, this icon with an ant will represent the failed content on the screen, replacing the placeholder
image.
How fantastic is that?
Of course, we can play with it for a while until we check out how all three Async Image Phases work.
By the way, it is not the only way to use Async Image Phases.
In the rest of the SwiftUI tutorial, I will show you an alternative mode of doing that.
However, to make this more interesting, we will add some animation to this Async Image and make it
really cool!
Animation. The process is the same. Select the fourth section code and comment out as I show you.
After that, let's create the final section and make the best of the SwiftUI's Async Image.
Enter the following code!
New comment, Mark 5th.
Animation.
Async image, you are URL, you URL, string image, you URL.
Phase.
In.
Padding 40. So far, the code is identical to the previous one.
However, we can utilize the async image phases enemies in this new sample code.
Let's do it right now.
Enter the following code switch phase.
Case.
Success.
Image.
Image dot, image modifier.
Case.
Failure underscore.
Image.
System name and dot, circle, dot i icon modifier case.
Empty.
Image.
System name, photo.circle.fill. Icon modifier.
As you can see, we used the Switch statement instead of using the traditional If, Else conditional.
The reason behind this is the following.
The Async Image Phase is actually an enumeration that keeps track of the current phase of the download
operation.
Knowing this fact, we can provide a detailed implementation for each of the phases, including
the empty, failure, and success phases.
This code is so elegant,
am I right?
Just one more thing!
As you can notice, there is a gently warning that the compiler gives us.
You know, this code works totally fine since we covered all available phases.
Yet, we should make our code more bullet-proof and less error-prone.
Click on the warning sign, and read what the compiler is saying about it.
There it goes!
Basically, software engineers at Apple could introduce more phases for the SwiftUI's Async Image
in the future,
and that's why we can avoid potential app crashes by providing a default value.
By clicking on the Fix button, Xcode will help us with inserting the missing code.
Do you see the new code at the end?
Just replace the fatal error with a simple Progress View.
That's it.
Now let's start the Live Preview and test the application.
Guess what?
The warning is gone, and our code works as it is supposed to do.
The only thing that is still missing the animation feature that I promised you before.
To animate the remote image, we need to specify an optional transaction parameter for the Async Image.
Navigate the cursor to the URL parameter and enter the following code snippet!
Transaction.
Animation Spring.
Response. 0.5. Damping Fraction. 0.6. Blend Duration. 0.25.
With this transaction, we defined what kind of animation we want to run each time when the image downloads from the Internet.
The final information that we still need to provide to work this animation is
some type of transition.
And o gosh! There are plenty of transitions that we can choose from.
In the rest of the tutorial, we will have some fun playing with some of the available transitions.
Does it sound good?
I hope so!
So let's do it! Go to the image and add this new modifier to it.
Transition.
Move. Edge. Bottom.
After that, let's refresh the Live Preview and see what's happening.
Whops! What a surprise that animation with Async Image does not work in the Preview.
Don't worry too much about it, since testing animation is always better on an actual device,
even we could do it in the Simulator.
With that said, build and run the application in the Simulator as I show you.
After the initial launch, we can see the picture icon in the empty phase, which works like a placeholder.
When the remote image is downloaded, then the chosen animation starts.
Now let's try out a different transition, shall we?
Jump back to Xcode.
First of all, comment out the move transition, then let's add a different modifier to the image. Enter: Transition. Slide.
Of course, we need to build the app and test the slide animation in the Simulator, so let's do it again!
Depending on the language writing direction, the remote image is sliding into the middle of
the screen from the left or the opposite side.
What an amazing animation that is!
Let's test it again!
But you know what?
Let me show you my favorite transition.
Jump back to Xcode and replace the previous image modifier with this one.
Enter: Transition.
Scale.
If you test the app on a real device or in the Simulator, then you should notice how great the spring
transition fits this scale effect.
I hope that you like the final result so much as I do.
We covered all features of Swifties async image from iOS 15. With building this mini-application, we covered all features of SwiftUI's Async Image.
From iOS 15, no third-party plug-in is needed if we would like to load remote image assets from the Internet.
Wrap Up. Just to recap the main features of this dedicated Async Image view.
To load an image from the Internet is as simple as providing an optional URL for the Async Image.
Next! By default, the image is assumed to have a scale of one, meaning it is designed for non-retina
screens.
We can change it by modifying the value of the Scale parameter.
Another thing is that we can not apply image-specific modifiers directly to an Async Image.
Instead, we must apply them to the image instance.
It's worth knowing that we can specify a custom placeholder and replace the default gray view.
Finally, we can also utilize the enum of the Async Image Phase in the content closure.
With this Async Image Phase, we can indicate the state of the loading operation.
And by doing that, our program returns a view that is appropriate for each phase, such as empty phase,
failure phase, or success phase.
In this SwiftUI tutorial, we covered many code examples of how to use the Async Image properly so you can implement this knowledge
into your development workflow.
I hope that you enjoyed this lecture and you are eager to start the next one.
Until then, happy coding!