Threading, Async & Await
The course is part of this learning path
Threading, Async & Await in iOS
Hi, within this lecture, we're going to change the code a little bit. So far, we have a working application, so it's okay, but we have to know about the new features of the concurrency and trading in Swift and iOS as well. So, we're going to learn a very important concept called, async, like in asynchronous and evade. So, I'm going to show you how to spell them and how to use them as well, don't worry about it. So, I found an article, so this has been written by some developer over here from Bolivia, I believe. And he has written out this article once the async and await features has been introduced to Swift. And in fact, I went to the developer.apple.com in order to understand how they work. And I made it work, however, this guy explained it in a much better way than Apple in my opinion. So, I'm going to share this with you as well, so that if you want to learn about the details of this, I believe this, Andy Ibanez is going to help you with that. Okay? So, I believe you should read this documentation or this blog post in your own time. However, I will explain how to use async and await and what they do and how to use it in a detailed way in a minute. So, what is async and await? So, I think is a keyword, it has two users. It actually tells the system, the compiler when a piece of code is asynchronous, so it's obvious right, so we can say that we want this function to be asynchronously executed, it's very good. And actually, automatically sponsors asynchronous tasks and all you got to do is just add this async after you ask the parameter to your function. It's very useful, right? So, it's very easy to understand, you can just add this async to a function and make it asynchronous. However, this is where the magic happens, as Andy says. The 'await' is a keyword again, but this keyword has the option to suspend the function, okay? So, I say it has the option because it is not definitive, you don't suspend the function or resume the function whenever you need it, system decides it. However, it's very convenient, all you got to do is just say await, and it executes that function in asynchronous fashion, and it suspends and resumes the function if it's necessary, and it completes the execution. It's very convenient for you. So, system decides whether to suspend it or resume it, but you get this capability of asynchronously executing a function, it's very powerful. So, how to use it, okay? And you will see the advantages of using it once we actually change our code to the async await syntax. So, how to use it. So, in the web service, we have these download currencies, and we are using the escaping at escaping syntax in order to make this work, and in order to wait for the execution to be completed to get the data. Right now, I'm going to write exact same function, but this time with async and await syntax. So, I'm going to say downloadCurrenciesAsync, okay? So, that's it. So, how do we make it async? So, over here, we're not even going to ask for the completion, of course, we're going to ask for the URL. But rather than the completion, I'm just going to say async and this will return the cryptocurrency list, like this, it's very easy, and it's much more clear, right? Rather than using this escaping, rather than using the result, I'm just saying that this will return me a cryptocurrency list. And of course, we just mark this with async. So, as you can see, it says that this is available for iOS 15 and later on. So, I'm just going to come over here and change this to be iOS 15, okay? So, I changed my deployment target, so I suggest you do the same as well. And this goes away, of course, it says that you're you're missing the return because it expects us to return a list of cryptocurrency right now and that's what we're going to do. So, eventually we're going to do that, but you can make this optional by the way, like we did in the below function like this, but let's do this with non-optional type this time and see how to handle that as well, okay? But it's easy for you, you can just do this with optional as well. So, rather than using the URL.session.shared.data task, which runs asynchronously by itself. Right now, I'm going to use this data. Again, this is going to be executed asynchronously as well, but as you can see it's marked with the async syntax. So, this is by default async, and throws an error, okay? So, this is a new feature of URL session available from iOS 15 and later on. So, we're going to see how to use it. One of them asks for a URL, and the other one asks for a URL request, so I'm going to go for the URL. And you don't need to specify the delegates in any case, so you can just delete that, and here you go. But as you can see, it says that this will give you a data and response, and we don't know how to turn this into a cryptocurrency. So, as you can see, it gives us data and response in the URL session data task over here as well, but this will directly return us a data and response, so you can write this like that. Let data and response be equal to your URLSession.shared.data. So, let's see the other things. As you can see, this is async, but we need to 'await' this. So, every time you use async in a function, you need to 'await' it in order to make that work, okay? So, this is inseparable, you need to use 'await' if you're working with something async. And of course, we're going to have to try this, okay? We're going to have to try this because it has to throw an error. So, if we actually add this try, it won't let us do that because we need to add do try catch, but I don't want to add do try catch at this point. Maybe I want to print the air over here, or maybe I want to display that error to the user, I don't know. So, rather than adding the do try catch over here, I'm just going to say this function throws as well and the error will go away. So, whenever I apply this function in some other viewer in some other class, then I need to do the do try catch. And right now, since I added this async and throws, I can get the data and response back. Now, what I'm going to do, I'm going to pass that data in order to get this cryptocurrency and just return it, okay? So, I'm going to do exactly what I have been doing over here. So, I'm going to say let currencies and try this. In fact, you can copy and paste, we're not going to change anything. We're going to try to decode this with the cryptocurrency model. And just return these currencies, that's it. So, since I didn't make the cryptocurrency optional, the return type optional as you can see, it gives me an error. If I make this optional, then the error will go away, and you can continue like this, okay? There is no harm in that, but if you don't want to make it optional, then you're going to have to say something like this. If this is nil, then return an empty array, okay? That's how we handle that situation. And since we're not using that response, it gives us a suggestion, so we can just do it like this, an underscore will be enough for that. Underscore means that I'm going to ignore this variable, okay? I'm not going to use it. So far so good, as you can see it's much more clear than this, right? At escaping the result and stuff, we're just going to say I'm going to return a cryptocurrency list, and I'm doing that. And I'm not using data task, I'm using data. Data is async by default. And since this is async by default, I'm using await in order to make this work. Now, of course, we need to change the script of view model as well, because we're using download currencies in here. And in fact, you can come over here and just delete this or make this a comment line, like this slash star and star slash and here you go. Now, we need to use the download currencies async rather than this. So, I'm going to go to the crypto view model, and in fact I'm just going to like, make this comment line as well. Okay. We're going to need them later on because we're going to see some other alternative ways of doing this as well. Don't worry about it. So, I'm going to create a new function called downloadCryptosAsync this time. And I'm just going to ask for URL one more time. And open the curly braces over here. Right now, what I want to do, I want to call the webservice.downloadCurrenciesAsync. And as you can see, it gives us an error. It says that this is an async, but your context is not async. So, even if I give the URL over here, it won't work. So, as you can see, it says that, "'async' called in a function that does not support concurrency." So, how do I do that? I need to make this function async as well, right? So, I'm going to say this is async as well, and that error will go away. Even if that error go away, as you can see, we still need to take care of this await situation. Since this is async, we need to await it. Okay? Remember, these are inseparable, and this will give us the cryptos back. That's it. But, of course, this can throw an error. Okay? It gives us the cryptocurrencies, but this can throw an error. That's why we are getting a lot of situations over here like these error messages. So, rather than await, I'm just going to say, try await. And again you can make the strolls or you can do the do-try-catch thing over here. Let's do the do-try-catch. And if we have an error, we can just catch the error over here. So, I'm just going to print out the error. And here you go. So, that's it. And after you get to cryptos, what do you do? You do the exact same thing that we have been doing so far. I'm just going to map the thing and let it equal to the crypto list. And, of course, we need to do this with dispatch queue as well. And later on, we're going to see how to get rid of this dispatch queue in a later lecture. Don't worry about it. I'm going to show you as well. But right now, I'm using this async function, and I'm awaiting the other async function that I have been writing so far. Right now, I can get the cryptos and it's much more clearer to me. So, I'm going to go to the main view. So, under onAppear, of course, we're going to get an error because we have deleted this downloadCryptos. So, I'm just going to make this a comment line. And here you go. Now, I'm going to call the new function. Okay? So, I'm going to say, cryptoListViewModel cryptoListViewModel. So, rather than download, I'm just going to say downloadCryptoAsync, and it will ask me for URL. But as you can see, there is a problem over here because onAppear is not async. Okay? Even if I give the string, even if I give the string and make everything right, it will give me an error because onAppear by default is not async. We can actually add the await over here, but the error won't go away. As you can see, it says that this is not an async function. So, how do we deal that? How do we deal with that? In the real model, we just converted function to be async, but we cannot do that with onAppear. So, rather than onAppear, I'm going to use something called .task. And here you go. So, I'm going to just do the same thing over here, and I'm going to comment out the onAppear because we won't be using it. And that task is a new feature valid up from iOS 15. And you can write the .task and add the await or async functions inside of it and make it work. Great. Now, we have solved that issue as well. And that is the only change that we need to do inside of the view, right? So, I'm going to run this. And we're getting an error in the web service. Yeah, I believe we have to delete this or just put it inside of the commented outline section. So, I believe, I commented out the wrong part. Yeah, here you go. Now, it's working. Now, let's go back to our simulator and see if this works or not. So, here you go. And here you go. It works. As you can see, we managed to download the data one more time. Nothing has been changed in the UI section, so users still sees it. But as you can see, we managed to do this with async and await. So, this is a great feature, and I believe you will be using it once the industry accepts it as an industry standard. So, we're going to stop here, but we're going to continue to see this in the next lecture as well.
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.