Threading, Async & Await
The course is part of this learning path
This course explores the concepts of threading, async, and await in iOS and how you can employ them in your app builds.
- Understand how to implement threading (aka concurrency) in your iOS apps
- Learn about the concepts of async image and await and how to use them
This course is intended for anyone who wants to learn how to develop apps on iOS.
To get the most out of this course, some basic knowledge of iOS development would be beneficial. We recommend that you take this course as part of the Developing Mobile Apps for iOS learning path.
Hi, within this lecture, we're going to see another way of converting a function into an async await syntax. So, let's start and see why do we do that and how to do it. So far, we have created async await. Okay? But we have written the function from scratch. If you remember the web service over here, we had this downloadCurrencies and we just deleted it and we just have it on a downloadCurrencies async function. And of course there might be a situation where you actually have a downloadCurrencies function or another function which is not async like this. But you want to convert it into an async syntax without having to delete it. So, we can create a new function and we can actually implement that function with async and await features without having to change the downloadCurrencies or the original function at all. So, why do we even want to do that? So, maybe you want to do that? But maybe you have to do that, maybe you don't have access to the downloadCurrencies function because it's a function that is written in a pod or in an external library, or maybe you're working in a project that is too big, or maybe you're working with 10 developers and someone has written a function which is not async and you want to execute it with async and await function, then you can create a new function that does that. So, I'm going to comment this out right now, and I'm going to leave the original downloadCurrencies as it is. I'm going to show you how to do that. I'm going to create a new function called downloadCurrenciesContinuation. We're going to see what is a continuation in a minute. And I'm going to ask for the URL again. Okay? And this will return the CryptoCurrency list again. So, there is nothing different from the downloadCurrencies async over here. And in fact, I'm just going to add the async throws from the scratch this time. Okay? Here we go. Now the parameters and everything is the same. However, I'm not going to rewrite that function. I'm going to use the downloadCurrencies function over here right now. I cannot just go ahead and use the downloadCurrencies. I need this Continuation functions. Why? Because this Continuation functions will actually give me the capability to suspend and resume the function when it's needed. Okay? So, as you can see, this is the UnsafeContinuation and CheckedContinuation and UnsafeThrowingContinuation and CheckThrowingContinuation. So, we have four options. We're going to go with the CheckedThrowingContinuation because we want to throw an error message if something goes wrong, and also we don't want to go with the unsafe version. I want to go with the checked continuation. So, these are all built-in functions that comes with the iOS 15 and later on. So, if you have Xcode 13 and later on, you can obviously reach them and you can use them to create async scopes where you implement the regular functions as it's needed. Okay? And this is async by default as you can see, so we're going to have to await it eventually. So again, this function will give us the opportunity to suspend and resume the function. Of course, we're not going to suspend it. So, the system will decide if we want to suspend it, but are we going to resume it? So, as you can see this has to be try await because this is a throwing and also this is an async by default. And if I hit 'Enter' as you can see, it gives me CheckedContinuation, which is kind of a result because you get a T and error eventually. So, I'm going to name this continuation. Okay? With a lower case c like this. So, what I'm going to do, I'm going to use this continuation to resume the task when it's needed. As you can see, we can return something. Of course, we're going to return the CryptoCurrencyList. And also we can throw something if we write continuation.resume. As you can see, it expects us to return an error once we throw something. Great. Now of course, before we resume it, we need to implement what we need to implement. This is being the downloadCurrencies. So, that's why we're doing this. Right?. So, I can just call the downloadCurrencies over here and give the URL that I asked for, and also implement the completion block as a result like this and switch case the result and just do what I have to do. So, I'm going to switch case the result and in the case of success, I'm going to get the currencies or cryptos out of this and I'm going to return that cryptos by using continuation.resume (returning). Okay? So, I'm going to give the cryptos over here, and that is the success case, which is good. And if this is nil, then I'm going to return an empty array like I've done before. And if this is a failure, I'm going to get an error out of this. And at this time I'm going to just say continuation.resume but not the returning but throwing and I'm just going throw the error. Great. Now, that's why we did that. That's why we used the continuation thingy. And I haven't changed this downloadCurrencies as I said before; maybe I don't want to change it, maybe I cannot change it if I wanted to, maybe I cannot reach it, maybe it's a getter but not, etc or something like that, maybe it's an external library, maybe it's a pod, and I can convert it to be an async await like this. So, right now I have to, of course, comment this out because we don't have a downloadCryptos async function anymore. I'm going to create a new function in the ViewModel saying downloadCryptos and continuation maybe this time. Okay? So, this will ask for URL as usual. And this will be async of course, because we're going to implement async function inside of it. So, I'm going to just get the cryptos out of this. I'm going to do the exact same thing. Actually, I'm going to say cryptos and we can just go ahead and try await webservice.downloadCurrenciesContinuation. Right? Because this is the function that we need to implement right now, of course, it will give us the error because we need to try and evade it. First await it. Maybe we can just try it, and maybe we can do try catch thingy. Great. Now, do try and catch. And if we catch an error, then I'm going to just print the area as it is. And great. Now the reason to do that, we need to pass this along to the cryptoList. So, I'm going to copy and paste this. We are not going to change anything regarding that, but we're going to get the cryptos from the new function right now. And that's it. That's it for the ViewModel. And let's go to the View. Of course, we're going to use the task again. Okay? Now this is invalid, I'm just going to make this into a comment. We're not going to use on appear, we're going to use task again because this is async by default and I'm just going to await the cryptoListViewModel.downloadCryptoContinuation and I'm just going to give the URL. So, let me copy and paste the URL from here, like this, to here, and put an exclamation mark, and here you go. Now, this is going to get the data from the downloadCryptosContinuation this time and everything seems to be fine. Don't forget to just comment and delete the comment lines for the downloadCurrencies or it won't work. Great. Now it's going to use the URLSection data task. This is not async await, but we have converted this to be async await using the continuation itself. Now what I'm going to do, of course, I'm going to try it and see if anything suspicious over here. Okay. Let's start it and see it in the simulator. Of course, nothing will change UI wise. Okay? The user will see the exact same thing. However we're going to have to try whether it works or not. So, let's wait and here you go. We get the data, it works smoothly so everything seems to be working but not this here. Here you go. So far so good. Now, we have seen multiple ways of converting a regular function into an async await syntax and it's good. But I said that I will show you how to get rid of dispatch queues as well. Now, it's time to do that. I'm going to stop here. And within the next lecture, we're going to discuss the actors, and how to use them in our code.
Atil is an instructor at Bogazici University, where he graduated back in 2010. He is also co-founder of Academy Club, which provides training, and Pera Games, which operates in the mobile gaming industry.