Multi-threading with background threads and queues in Xcode | Continued Learning #17

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is up everyone welcome back as you already know i'm nick this is swiffle thinking and in this video we're gonna look at using background cues or background threads now if you've never looked at threading before you might not even realize that there are multiple threads in your app and basically behind the scenes in your app there are a bunch of different threads that we can do processes on that we can perform tasks on and almost all of the code that you write into your app is going to be declared on the main thread which is thread 1 unless you specify otherwise and the main thread can take on a lot of tasks but if you start developing more complex apps you're going to end up doing a lot of stuff on the main thread and if you do too much it will start to slow down your app it could cause your app to freeze and possibly even crash so what we do as professional developers is take some of our heavy tasks that are happening in the background like downloading from the internet we can download images download pictures all that we could put on a background thread and basically all we have to do is tell xcode that instead of running this on the main thread run it on a background thread and there are a whole bunch of background threads that we can choose from and apple actually provides us an easy way to access a bunch of those background threads which we're going to look at in this video the number one most important thing about threading is to remember that anything that updates the ui so updates the actual screen needs to be performed on the main thread so as i'm going to show you guys we are going to start on the main thread when we open our app we are going to jump onto a background thread and perform tasks but after performing those tasks just before they are actually going to update the screen we're going to jump back onto the main thread and then update the screen so it's a little tricky if you've never learned this before but i hope this video makes it a little clearer multi-threading is something that is done in pretty much every production app that i've seen and very important to know as developer all right welcome back everyone i am back in our xcode project and for this video let's create a new file for all the code we're going gonna do in this video so let's right click on the navigator create a new file it's gonna be a swift ui view as always and let's call this background thread boot camp go ahead and click create once you're inside click resume on the canvas just to make sure we're all connected and let's get ready to get coding and to begin we're going to set up a view model for our view here so let's create a class we'll call it a background thread view model and let's make it conform to observable object so that we can observe it from our view and while we do this let's create let's initialize a new one in our view let's use an at state object var let's call it vm for view model and we'll set it equal to a new background thread view model all right let's set up our view here real quick and it's going to be very simple because most what we're going to do is actually in the view model so for the view let's create a scroll view open the brackets inside let's create a v stack maybe with some spacing of 10 open the brackets at the top let's add a very simple text that says load data let's make it font large title font weight of semi-bold because that looks good let's click resume on the canvas just to see what we're working with here load data and in the view model let's create an at published var we'll call it a data array and it'll be of type array of strings and we'll set it equal to a blank array we're going to then take this array and loop on it in our view so in our view we'll add a four each open the parentheses we're going to use the completion with the id and we're going to pass in the vm our view model dot data array the id will be backslash dot self then the content will press enter get rid of this completion here and just say we'll loop on each data so each item let's call it an item actually this will be each item in the data array and it's a string so we'll just put this text on the screen we'll say text with the item let's give these items a font of headline and a foreground color of maybe red it doesn't really matter this is just a very simple screen here and in our view model we're going to create a function to load some data we're going to say func fetch data open close parentheses open the brackets and our fetch data is actually going to call another function so let's create the other function that's func download data open close parenthesis open the brackets and this download data function is actually going to return some data so we're going to make it return an array of string here and in your real app obviously this download data is going to go download something from the internet but we're not looking at that right now so we're just going to create some fake data so let's create a blank array we'll say var data of type array of string equals equals a blank array and then we'll just say for x in zero dot less than a hundred and we'll open the bracket so this is gonna loop from zero to ninety nine and for each of those loops let's just call data.append and it needs to be a string so we'll create a string and we'll use the backslash open close parenthesis and we'll pass in the x and on each of these loops let's just then print out the data so this will print out the data array on each loop and after the loops let's just return the data so this shouldn't be anything new to you guys we're just going through 100 loops adding of adding 100 numbers to the data and then just returning it in our fetch data we'll say let new data equals the download data and then we'll say data array equals new data while we're here let's make the download data private so that it can only be accessed within this file and this will be our public function which we can access from the view so down in our view here on the load data i'm going to call very simply on tap gesture vm dot fetch data okay so if i resume the canvas let's just make sure it works quickly and then we will check out why we're doing this so i'm going to resume the canvas here and if i tap on load data it should then create our 100 items alright so this shouldn't be anything special but let's actually run this on a simulator now so i'm going to take this background thread boot camp i'm going to jump into our app.swift file this should be where you're at main call is i'm just going to make the first screen in our app the background thread boot camp then i'm going to make sure we're looking at an iphone 12 and then run it with this play button to run on a simulator i'm going to jump back into our file quick and i'm going to actually hide the canvas because we're not going to use it anymore and let's look at our simulator that should have just opened up so before i actually click anything on this simulator i'm going to open up a new tab in xcode that we haven't used yet so on the navigator on the left side here there is a little icon that looks like a spray bottle that is the debug navigator so let's click on that and then we're going to click on the cpu tab here and if you're following my courses this is not something we've ever used before but basically this is a quick little gauge on the computing power that your app is using so if you so obviously this is a very simple app and we're at zero percent right here because nothing's really happening on the screen but if you're ever building a very big and complex app you should definitely be checking the cpu and seeing if it's high if this bar is red and this is very high chances are you're not doing something as efficiently as you could and if the percentages gets really high your app could even start to slow down or lag or even freeze so you really want to keep this as low as you possibly can and one of the ways to fix when this gets high is to use background threads or multiple threads and that's we're going to discuss right now so if we look down here at the bottom there is a thread section and this and this is all of the threads in our app and you can think of these kind of as engines so thread one is the main engine it's it's called the main thread and this is where almost all of the code that you write will happen by default on this thread one so when i click load data it's going to loop through all of that data that we just set up and then add them to the screen and we should see a little spike on this thread one here so i have this little blue line you can barely see that's the current time so we're going to look right around here and then i'm going to click on load data and we should get a little spike so you can see that this happened on the main thread on thread one and when i start scrolling around the screen you'll see that all that functionality is happening on our main thread so this is great and our main thread is pretty powerful we can do a ton of stuff on the main thread without ever having problems and you can see here the percentage used while i'm scrolling is still only four percent five percent so this is not something i would even worry about in an app and basically what happens is when you have too many tasks going on on this main thread it will get kind of stuck and it will slow down and when the thread slows down uh your entire app will start to slow down so if you've ever used an application and you're scrolling and all of a sudden it felt a little laggy or it started to slow down a little bit or maybe it froze for a second that probably happened because the main thread got stuck there was too many processes going on on the main thread it needed to just handle all those processes before the ui could continue so i want to point out here that while i'm scrolling around and even if i click load data to keep loading more data all these processes are happening on the main thread we don't see any spikes on thread four and there actually could be a whole bunch of other threads here we just have never used any of these other threads in our app so we only see these ones all of our spikes are on the main thread and again that's fine for most processes but sometimes you're gonna download data from the internet or do pretty heavy tasks and the solution here is to offload some of these tasks to a background thread all right so let's jump back into our file i'm going back into the background thread bootcamp and i'm going to go up to our view model here and this function download data is getting called right here and i'm going to put this on a background thread this time so all these print statements are going to happen on the background so apple actually gives us a bunch of background threads that we can use that are super handy so here i'll call dispatch q dot global and we can use the regular global completion here or we can use the global and specify a quality of service let's start with just the global and then we'll call dot async and all we're going to do is put this code into this thread now when we put our code into this async closure here we're going to get these error messages that we need to reference self dot explicitly and in the next video in the series i'm going to explain what this self is and how we can use weak self to better manage this but for right now the easiest way to think about this is when we call this async this code here inside this closure is happening on a different thread right so when we just looked at all of our threads i'll go back to it normally we're on the main thread but now we're going to go on a background thread we're going to go on a different thread so when we go to another thread we basically need to ensure that we still have a reference to this class which is referenced on the main thread so by calling self dot it basically creates a strong reference to this class so it knows that this download data is actually in this class here so very simply we'll just add self dot and i'm going to explain that more in detail on the next video before right now we just added this dispatch cue dot global which is a background thread and we're going to call all this code on the background thread so when we print this data it should be happening on a background thread and this is going to throw a warning error when we run it and i'm going to run through that in a second but for right now let's just take this code let's rerun our app and we're going to try this one more time i'm going to jump back into the cpu page here all right so you saw before that when i was when i clicked load data we got a bump on that main thread but this time when i click load data it should open up a background thread here so if i click it we should see a spike and use this spike was on thread three and if and if i click load data a bunch more times to keep calling that function it should keep happening on background thread so we can see thread 11 down here is now doing stuff and this is slightly better because we've offloaded some tasks from the main thread onto this background thread now two things i want to point out here that are very important the first thing is that when i move around the ui it is still on the main thread and this is important because anything that affects the ui needs to be done on this main thread so in our situation when we're on a background thread we could download data and we can manage data but if we're going to do something that updates the ui the front end of the actual application we need to go back on to the main thread so on your xcode you probably got this purple error message here that you've probably never seen before and if i click on it it's going to bring me back into where our issue is and it very directly says publishing changes from the background thread is not allowed and just as i was talking about we can go and download data on background threads and process data and move data around maybe save data in our application or to our database but if we ever want to return back and do something that updates the ui so in this case if we update the data array it's going to update the view here so anytime we update this data array it needs to be done on the main thread not on the background thread and that's why we're getting this error so very simply before we update the data array we will go back onto the main thread and we do this by calling dispatch q dot main dot async so it's almost the same call here this was a global this is the main and main is that thread one that we've been looking at and i'll just put this code into this call here so we'll go to the background thread download the data on the background and then when we're ready we're going to hop back onto the main thread and then update the ui so now when i run it we shouldn't get this purple uh we shouldn't get this purple error message anymore i'm gonna press run again i'm gonna go back into the cpu page here we have our load data and if i click it we should get a spike on a background thread and that happened on the main thread because it was updating but we should have also done some stuff on the background so i'm going to click it a bunch of times and see if we can get some spikes alright so you can see that some of the processes are happening on thread three here and some and of course some processes are still always going to happen on thread one because after we go to the background thread and we download the data on thread three we're going back onto the main thread to update the ui so that's why thread one is also running as well as thread three and i wanna dive into this a little bit deeper because we can use other threads instead of just thread 3 here so if i go back into the code we called global but we could also call global with the quality of service and this is super handy that apple gives us if we press the period on this quality of service there are a couple different background cues that we can use going down this list here the first one is a background and it gives us a nice description here that this background choice should be used for maintenance or cleanup tasks that you create so this could be things that maybe you need to do in the background that the user doesn't even know about then we have the default quality of service we have the unspecified which is not specifying which one you actually want to use we have the user initiated option and this is pretty interesting this this class should be used for tasks that prevent the user from actively using your app so it's almost like scary to read so this should be used for things that are so crucially important that the user can't even use your app until this loads so user initiated i would use for like the most important things but also use it sparingly because you know if you're doing something that's going to prevent the user from actively using your app you don't want to run into a situation where your app is actually frozen because this task is running and it's preventing the user from clicking around we also have the user interactive which is for tasks such as animations event handling updating your apps user interface so this is a pretty common one to use and lastly we have the utility and this is for tests the user does not actively track so offhand i find that i use this utility mostly for things that the user doesn't even know is happening so stuff that i've added into the app that i want to perform but the user doesn't even know those functions are running so of these let's just use the background one for now and this time when we run it it should actually put these tasks on a different thread than thread three which we saw last time and i'm going to go down here to the view real quick and just make this v stack let's make it a lazy v stack so that a little bit less operations are happening on the view and let's run our app one more time let's jump into the cpu and we have our load data and when i click the button hopefully a new thread will open up in the background and when i start clicking the bottom i click it a bunch of times here we can see that some of the processes are happening on thread four and then when it's going back onto this main screen it's happening on thread one and it looks like it even opened up a new thread halfway through this we're now on thread nine and also thread one as well and if i scroll around all the ui stuff is still happening on thread one so we can see all the spikes on thread one but when we're using that download data it is happening on thread 9. so i know this kind of seems anticlimactic because all we're doing is looking at these little tiny spikes but this is crucially important when you start doing heavy processes because if you're like downloading something from the internet especially if it's a video or movie or picture those are heavy processes that you want to put on background threads you don't want to run those on the main thread but after you download all that data you need to go back onto the main thread to update the ui so that's kind of what we simulated here and the last thing i want to show you guys before we finish up this video is a quick little check that you can do in your app if you're ever curious on what thread you're on so there's very simple way of checking whether or not we're on the main thread and we can do that by calling thread dot is main thread this will tell us whether or not we're on the main thread and similarly we can call thread dot current to get the actual current thread that we are on so i'm going to actually just print these out so that we can see what we're doing so let's print uh let's let's call this uh check one and then we'll print um thread dot is main thread i'm going to copy and paste it and here we'll print thread dot current then i'll copy both of these and paste them also down here and let's make this check two so let's run the simulator one more time and this time when we go to download that data we should see these check ones and because we're on this background thread this should be false this should be not thread one and then when we go back onto the main thread his main thread should be true and then current should be one so let's open up the console here let's click load data and for check one we have false and the thread is number four so this is not on the main thread that's this check here and then we returned back onto the main thread and it went back to true which we can see here and thread is number one all right guys i hope that wasn't too confusing i know it was a lot of me talking for just a little bit of code but these background threads are crucially important this is something that i wish someone had told me more about when i was learning how to code because uh if you don't know about it you'll end up doing all of your tasks on the main thread when it would be much more efficient to offset some of that payload onto background threads the number one main important thing here to note is that you can do tasks on the background thread but if something is going to affect the ui if it's going to change the screen you need to do that process on the main thread if you're still confused do not worry because we're going to start using these threads a lot more in the next couple videos as we start to download data from the internet and manage that so i hope you guys are as excited as i am thank you all for listening as always i'm nick this is swiffle thinking and i'll see you in the next video
Info
Channel: Swiftful Thinking
Views: 2,401
Rating: undefined out of 5
Keywords: SwiftUI Background Thread, SwiftUI background threads, Swift background thread, Swift background threads, Swift background queue, SwiftUI background queue, multi threading swift, multiple threads swift, swift multiple threads, swift main thread, Swift how to use background thread, Swift use background thread, Swift how to perform on background thread, swift queues, Swift dispatch queue, How to use background threads swift, How to use background queues swift, Swift, SwiftUI
Id: jEpg2SYvVV8
Channel Id: undefined
Length: 23min 48sec (1428 seconds)
Published: Sat Apr 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.