SwiftUI Continued Learning #18: How to use weak self in Swift

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what's up everyone welcome back i'm nick this channel is swiftly thinking where we cover all things swift and swift ui related and in this exciting video we're going to look at weak self we're going to learn what exactly weak self means and why we use it and i'm super excited to share this because this is something that i wish someone had stressed and explained to me more when i was learning app development it's often overlooked as people start to learn app development and a lot of beginner courses don't even touch on it but it is very important in order to get into excel we first have to understand automatic reference counting and you can google this arc automatic reference counting and apple probably has a bunch of articles on exactly what it is but basically every time you make an object or a screen the system is holding a reference to that object so reference counting by itself is pretty simple but as developers we want to keep this count as low as possible because it makes our app more efficient and faster and often times in your app when users are moving around the app behind the scenes the app is actually de-initializing screens and views that the user is no longer using so this is efficient so if they go to the screen and then press it back that screen might get de-initialized so any objects that were created on that screen would then be removed from our account and this is great but sometimes in our app we end up writing code that doesn't allow that screen to de-initialize when we actually want it to and you might not even realize you're doing this but you basically are creating a strong reference to that screen or that object and the solution is to basically create a weak reference instead of a strong reference and that's kind of what weak self is now i'm covering it right now because in the next bunch of videos we're going to start downloading data from the internet because when we have these functions that are going to the internet and then coming back it becomes super important to understand these strong and weak references and you're probably going to want to use a weak self a lot of times so i hope this doesn't get too confusing for some of you guys leave a comment below if you are still confused but i think the example we're going gonna go through uh really helps to explain it all right and if you are enjoying this content please don't forget to hit the like button and the subscribe button to stay up to date with all of these videos and this playlist all right welcome back everyone i'm back in xcode as always in this video we're looking at the week self call and we're going to do that in a new file so let's right click on the navigator create a new file it's going to be a swift ui view and let's call this week self boot camp go ahead and click create once you're inside click resume on the canvas and this again is something that i wish someone had talked to me a little more about when i was learning to code because because this is very important when you actually make applications and i don't think a lot of beginners even think about something like this so some of what we're doing here is a little bit abstract so i try to find the simplest way to explain this to you guys and what we're going to do is create a navigation view on our screen we'll add a navigation view open the brackets inside the navigation view is going to be a very simple navigation link open the parentheses we're going to use the uh let's use the string protocol and destination the title will say maybe navigate nothing important here and then the destination we're going to change in a second but let's just make it a text right now with a blank string and let's create a second screen here so underneath this struct i'm going to create a new struct let's call it weak self second screen it will conform to view just like our main view and every view needs a body and we'll open the brackets the body here is gonna be very simple just gonna be a text that says second view let's give it a font of large title and a foreground color of red let's add this into our destination so we'll do weak self second screen let's click resume in the canvas just to make sure it all works let's also add a navigation title here screen one all right so on screen one we can press play here on the sim on the canvas click navigate and it should bring us to the second view alright so this is a very simple app if you're confused at this point you should probably go check out some more beginner videos on my youtube channel because this should not be anything new to you guys this should be very simple we have two screens in a navigation view we can navigate we can press back and here we are all right this second screen is going to have a view model so we're going to create that now we'll do it underneath this struct we'll say class let's call it weak self second screen view model i know it's really long to type here the name doesn't really matter let's make it conform to observable object as always open the brackets and we're going to create a at published in here this will be a var we'll call it data and it'll be of type a string we're going to make it optional with a question mark we're going to set it equal to nil for now inside this view model we're then going to create an init open and close parentheses open the brackets in this init let's print out initialize now and we're going to call function to get data so let's create a func get data open close parenthesis open the brackets from in the init we'll call get data so as soon as it loads and in get data we're just going to call uh data equals new data before we leave here let's also create a d init which is pretty much the opposite of an init this happens when the screen gets initialized this happens when the screen gets de-initialized and let's just print here we'll print d initialize now all right the last thing i actually want to do is put this data this string onto the second screen so on the second screen let's first add the view model we'll do in at state object var vm for view model equals the weak self second screen view model and let's hold the command button click on this text let's embed it in a v stack and below the second view text we'll just add we'll say if let data equals vm.data open brackets so if this is data so if this is actually a value and not equal to nil we'll then add a text here and we'll put in the data all right if i click resume on the canvas let's first check that this data is loading in let's click navigate and it says new data perfect and now let's run this on a simulator so i'm going to take this so i'm going to take the first screen here which is our weak self boot camp i'm going to jump into our app.swift file i'm going to make this the first file in our app make sure we're on an iphone 12 you can do it on whatever simulator you would like i'm going to do an iphone 12 and let's run it on a simulator i'm going to jump back into our file here as well i'm going to close the canvas and you can ignore some of these warnings that that are coming through right now it's just some swift ui uh stuff that apple's probably working to get rid of and i'm gonna and i'm gonna actually just scroll down here and just press enter a bunch of times to break this out but when i click navigate it should initialize a view model so let's click navigate initialize now i'm gonna go back and i'm gonna press navigate one more time and we clicked it the second time it initialized the new one and de-initialized the first one and i'm going to press back and forward and back and forward and you can see here every time we go to this screen it is de-initializing one and initializing a new one okay so let's create a quick little variable on our screen just to track how many are initialized at a time so we're going to do a quick kind of little hack here we're just going to create a user default so on our first screen here let's do it um let's do it on top of the navigation view so on at the bottom of the navigation view i'm going to add in dot overlay and let's add a text for the number one for a second let's see if we see it let's go to background of color.green uh sorry let's open up the canvas so we can see what we're doing all right we can see our number here let's give it a font of large title let's add some padding and let's give this overlay a we'll use the comma and we'll add alignment of maybe top trailing just so it's on the top right here at all times let's give that background a corner radius 10. all right so this is how many are initialized right now so this number one let's make it track and a user default and i covered user defaults in another video so i'm not going to go over how they work in this one you can check out my other videos on app storage but let's create an app storage we're going to use a key here and this will be uh let's just call it count this will be a var and we'll we'll call it count and this will be of type int and it will be optional in case it's not set yet and we're just going to put this count into the text here so we'll do a backslash open close parenthesis put the count and because it's optional if there is none let's do two question marks and have it be zero if i click resume it should work we got zero and now every time we initialize very simply let's first get the current counts we'll say let currentcount equals userdefaults.standard.com int integer for key and the key is count remember this key is the same as the key that we just did up here and remember we're using user defaults down here because we are not in a view but because we're in a view we can use app storage up here i covered this all in the app storage video so i'm not going to cover that again right now but this will be the current count and then we're just going to set userdefault.standard.com set and we're gonna look for the integer and we're gonna set current count plus uh one and this will of course be four key count and when we go to d initialize let's copy these two lines and we're just going to do minus one on the d initialize okay so every time we initialize we add one every time we de-initialize well minus one so these should be equaling each other out and the last thing i want to do here is actually on that first view every time we load the app let's just start the count back at zero so we'll do init and here we'll just set the count equal to zero all right let's run the app on a simulator quick our count is zero and when i go to navigate count goes up to one and if i go back we can see our prints are coming through our initialize now if i go to do another one we initialize the new one but we also de-initialize the old one so the count is still one if i go back and i go forward and i go back and i go forward i can do this a whole bunch of times and the count is always one so this is great and this is efficient right because if this count kept going up it would be saving the memory of all of those old screens but right now our count remains at one and this is perfect the problem comes into play here when you are running asynchronous tasks so right now this is just happening immediately when we call getdata and if everything is working fine and we're all happy so if you watch my last video we were going on the background thread we were using a dispatch queue.global.async and when we put our call into that call we got this error message that the reference to data required explicit of self and to fix it we went self period and this was creating a strong reference to this class and when you're doing this creating a strong reference basically what you're telling the system is that while these tasks are running this self so this class absolutely needs to stay alive because we need that self when we come back and right now this is a very quick task so it wouldn't actually be a problem but if you were downloading like a lot of data from the internet the code in this async task might take a couple seconds it could take like 10 seconds and during that time the user could be doing something on the app like maybe pressing the back button and by the time the call comes back you might not actually need this self to be alive because maybe the user's already gone they're on a different screen they don't need this data anymore to so to simulate a very long task we're going to use dispatch q dot main dot async after this just creates a delay and we'll do dot now plus let's do something absurd like maybe 500 seconds and then we're going to press enter on here and we're gonna take our code and put it in here we're gonna get rid of this first call and basically what we're simulating here is a very long uh background task so this task will take 500 seconds that's a very long time and when you're downloading data from the internet it's not going to take 500 seconds but it will take some time and that's kind of what we're simulating with this line of code here so after 500 seconds the data should then update so let's click play on the simulator one more time let's we're at zero let's navigate to that second screen and it goes to one so we're looking good and now we're gonna go back and we go to navigate again it goes to two we haven't seen it go to two before and if we look at our printouts the initialize was called twice but d initialize was never called and the reason the d initialize was never called is because we had this strong reference to self here and when we had the strong reference to self we told the code that that class could not be de-initialized until this closure completes so after this 500 seconds this will then call this will then be complete and then it will de-initialize but until this 500 second completes this self will always stay alive in our code so for some things that could be good if we absolutely needed this line of code to happen but a lot of times in your app like what we just did within that time frame that 500 seconds the user navigated away they went to another screen and so once they did that we didn't really need to update that original screen that they were on right because they're gone they've moved on they're doing other things in the app so the fact that we keep this alive is actually not efficient and we can see here that if i keep on navigating back and forth our count is going to keep going up because we're creating all these strong references and what's happening behind the scenes here in the second view we're creating these view models and right now there are eight of these view models alive in the background of our app and the fact that we're only on the screen here on one of them just proves that this is not efficient because we now have eight classes in the background and we only really need one right we only need the one that we're on right now we're never going to get back to that old screen so you could imagine that if you created these strong references all around your application when you're using this self dot you're going to get a ton of objects all around your app that are alive that don't need to be alive and when you have all this extra stuff in your app it is just going to basically weigh down the app and it could slow things down so as the developer this is very important because this could definitely slow down your app so the solution here is basically instead of calling itself with this strong reference which means we absolutely need this class to stay alive we could instead add a square bracket and say weak self and then add the word in and this weak self basically just makes this self instead of being a strong reference it turns into a weak reference and we're gonna get a quick error message here that it is now optional so we can fix it with the question mark and basically this code is the exact same as we had except self is now optional so we still have reference to this data that we can update but we're telling the code here that we don't absolutely need this class to stay alive so if this class for whatever reason gets de-initialized it's okay and we can just ignore whatever these calls are so if i run my app one more time and i start clicking forward and back you'll see that the you'll see that the number stays at one again because even though this call didn't come back this reference to self was weak it wasn't strong so because it was weak we allowed it to de-initialize and we got our de-initialized calls back here so generally speaking in your app when you have these long tasks that you're like downloading data for the user it's very important to add this weak self because if you're downloading data for the second screen and then the user goes away to another screen you don't really need that first screen to stay alive anymore and if you kept that screen alive it would stay in the memory it would start to slow down your application and it just wouldn't be very efficient alright guys i hope that wasn't too confusing um basically the bottom line here is by using weak self we can make references to classes and to self optional so that we're telling xcode it's okay if this class de-initializes because if we have a strong reference it's telling xcode that we absolutely need the class to stay alive and in that scenario you would run into situations where this number keeps going up and you can imagine in your app if you had tons of calls all over your app and all these extra classes and objects were staying in the memory it could definitely weigh down your app and slow things down so to be professional efficient expert developers we use weak self a lot of the times when we're doing things that are asynchronous tasks such as downloading data from the internet alright guys i hope you enjoyed this video uh as always i'm nick this is swiffle thinking and i'll see you in the next video
Info
Channel: Swiftful Thinking
Views: 1,573
Rating: 4.9703703 out of 5
Keywords: SwiftUI weak, Swift weak self, what is weak self, weak self swift, weak self SwiftUI, SwiftUI weak self, What is weak self, Swift what is weak self, SwiftUI what is weak self, what is weak self Swift, what is weak self SwiftUI, Swift how to use weak self, SwiftUI how to use weak self, weak self in Swift, automatic reference counting, swift ARC, swift reference counting, swift weak self help, what is weak vs strong reference, weak vs strong swift
Id: TPHp9kR0Go8
Channel Id: undefined
Length: 20min 33sec (1233 seconds)
Published: Sun Apr 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.