Modern Concurrency: Beyond the Basics

Oct 20 2022 · Swift 5.5, iOS 15, Xcode 13.4

Part 2: Concurrent Code

15. Writing Safe Concurrent Code With Actors

Episode complete

Play next episode

About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 14. Actor Next episode: 16. GlobalActor

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

In the previous episode, you converted EmojiArt model from a class to an actor to protect its verified count property from data races. In this episode, you'll mix actors, tasks, and Async 08 to solve one of the eternal problems in programming, image caching. You'll use an actor that fetches the digital emoji assets from the core server and caches them in memory. Continue with your project from the previous episode or open the starter project. Then open the file image loader.swift in the model group. This actor manages a cache dictionary to store the in-progress downloads. The image is already downloaded into memory and any attempted downloads where the server returned an error. Image Loader has methods to add images to the cache, start a new download, and clear the cache. Actor methods that can directly mutate cache. So the add method just sets the value for the given asset key to completed image. The image method fetches a single image from memory or from the server. If the asset isn't in the cache, the method downloads it from the server in a detached task. Once the task is ready, the method adds it to cache as an in progress value. If the same asset appears in the feed again, the app won't download it a second time. Instead, it will wait for the ongoing download task to complete and return the fetched result. And finally, it handles the result of the download. It waits for the download task to complete, then calls add to add the image to the in-memory cache and return it. If the task throws, it updates cache with a failure value for this asset before rethrowing the error. This third method clears the in-memory cache for debugging purposes. That's the Image Loader actor. Now you need to share it with all the views. Since you'll use Image Loader in a few different views, you need to inject it directly into the Swift UI environment, so you can easily access it throughout your view hierarchy. To use it as an environment object though, it must conform to observable object, even though it doesn't have any published properties. In Image Loader.Swift, add an observable object conformance. No complaints from the compiler, so move on. Open app main.swift. Instantiate Image Loader and pass it to list view as an environment object. Now you can use Image Loader from any view where you need images. Open the views group. Thumbimage displays a single asset in the image feed, so this is certainly a place where you'll need Image Loader. Open Thumbimage, and add and Image Loader property. This line initializes the injected Image Loader. You'll use it to fetch the asset image. In the view body, add a task right after overlay. So when the thumbnail view appears on screen, you call imageLoader.image to fetch the image from the cache or from the server. If the image method fails, you set an overlay for the thumbnail to show the user that the image load failed. If the image method returned an image, you update the view image, build and run. At last, you can enjoy some cool EmojiArt. If you see a few question mark images. That's because the server omits a few to simulate missing images. The server image feed returns some duplicate assets, so you can play around with the scenario of getting an already cached asset and displaying it. When you look at X Codes output console, you'll initially see some download logs like these. Scroll all the way down to the bottom of the feed and back up again. Download logs have stopped appearing in the console, even if you keep scrolling up and down. Once you've downloaded all the assets, you only fetch images from memory. Next, you'll add code to detailsview.swift to display a larger version of a selected asset. Add the same Image Loader environment object property. Add a task modifier just below the existing foreground color modifier of the Z stack, build and run. Tap an image and enjoy the details preview. Congratulations, the EmojiArt Online catalog app is complete for now. However, when you quit the app and run it again, it needs to fetch the images from the server all over again. They don't persist on the device. In the next episodes, you'll learn about global actor, then create a custom global actor to upgrade your app with a persistent on disk cache.