Memory 3 - Fixing Memory Leaks in Closures with Capture List (iOS, Xcode 9, Swift 4)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone my name is Mark Mohicans from Big Mountain studio and welcome to the third video in the Swift memory mastery series if you haven't watched the other two videos I recommend you go back and watch those now because we're going to build upon the knowledge that you learned from them so in a previous video we learned a little bit about automatic reference counting we learned about finding memory problems using the leaks instruments tool and then we fix those memory problems using either weak references or unknown references now in this video we're going to take that knowledge a little bit further you're gonna learn about closures if you don't know what closures are right now don't worry about it I'll explain it and go into detail as far as what they are and then we're gonna look at how closures can cause memory problems it's actually like one of the easiest ways to create a memory problem and a lot of developers don't know this so I'm gonna show you some handy tips on how to fix those how to find them and then how to fix that yeah it looks like it's about it okay I hope you guys enjoy this video and yeah it looks like it's about it okay this is part three of the Swift memory mastery series if you haven't seen part 1 or part 2 in this content maybe a little bit confusing because we're going to build off of that previous knowledge so if you haven't watched those videos please watch them first so you're not overwhelmed or confused by this video all right thanks before we begin there's something you must know and that is what a closure is now I know you've probably seen and even used closures without fully knowing what they are Apple says that closures are self-contained blocks of functionality that can be passed around and used in your code if you come from an objective-c background then this is similar to a block in c-sharp and other languages you might know them as lambdas or anonymous methods so basically it's a function with no name that can be passed around so let's look at some examples here we probably see the most simple example of a closure a closure which is basically some code between braces is assigned to a variable but what can you do with this well you can call it later on in your code somewhere just like calling a function you can also pass it into another function as a parameter if you want so in this case call some code accepts a parameter of a closure type and we're just passing in our closure in here and then call some code will execute that closures code okay so if closures are like functions without names how do you pass in parameters or return a value for example let's look at this function how could you create a closure that represents this function here we pass in a name and we return a string well you still use the parentheses with the parameters defined inside followed by a return type just like the function except in a closure you separate the parameters and the return type from the rest of the code with the in keyword in a previous series about reusable pop-ups we assigned a closure to a class property this closure we get called later on by the pop-up class so why am I telling you all of this this is a course about memory right what a closures have to do with memory I'm teaching about closures because there's one important fact that you have to understand and that is that closures are reference types that's right a closure is its own object with its own address in memory much like a class has its own memory address while so does the closure so in this example this closure this reference type is being assigned to the on save property and it has its own address in memory so what do you know about reference types well there's only one copy in memory in what actually gets passed around is just a pointer to that memory address okay now I want to prove to you that closures are actually reference types let's go back into this project that I created to demonstrate reusable pop-ups okay so what's happening in this view controller is there's a UI with a button on it and when I click the button it's going to navigate to a date pop up view controller which you see right here we assign some values to the properties on the pop-up including the unsaved right here we assign a closure to the on safe property so let's go take a look at this pop-up here I'm going to hold down command and right click on it it's gone a vajayjay pop-up view controller and I have a breakpoint set right here so when we come into the viewdidload we're gonna stop and we're going to check out the memory of this class here so let me just run it okay where this class is is actually on the second tab here I'm gonna click navigate away and it's when I click this button that we're going to go into the pop-up view controller and hit our break point okay now we hit our break point and I want to look at these properties on itself which is the pop-up and this is the one I'm particularly interested in is the on save so notice the on save which has our closure assigned to it has its own memory address right here and there's another message that goes along with it reusable pop-ups partial apply forward or foreclosure number one actually I don't even know what that means I tried looking it up on the internet but I wasn't able to find any good answers as to what that actually means so if any of you guys figure out what it means please leave a comment below and teach me because I had a hard time finding the answer but the main thing I want to show you here though is that on save our closure has its own memory address okay good now you know that closures are reference types and as a reference type they have their own memory address and there's only one in memory and whenever you pass it around you're passing around a pointer to it so as a reference type they can also create their own memory problems it is especially easy to create retain cycles with closures and as we continue I'll show you how this happens but first notice that inside this closure we're referencing this view controllers date label now let's see what this dependency chain might look like if we create a memory graph starting with the date pop up view controller all the way to this date label starting with the date pop of view control at the top it has a property called unsaved which is a closure and notice I created a separate object for the on safe because it is its own object it has its own memory address and then inside of that closure unsaved references the view controller which is represented by the word self and it references self so we can access the date label because we want to set some text on that date label okay let's take a look these arrows here and we notice the day pop-up view controller has a strong reference to the on save and inside that on save closure it has a strong reference to the view controller which has the label and the label itself is a weak reference because if we look at the code notice it has the word weak there and usually when you create outlets inside of your controllers they're almost always weak I don't know if I've ever seen outlet that wasn't weak maybe it can happen but I really haven't investigated it so I'm not sure but I'm pretty certain that most of the time they're always weak references okay now I mentioned before that closures can cause memory problems so let's see how this can happen now what I've done here is I've changed the code to introduce a problem we now have a new property at the top called pop-up so what's the problem with this you might ask this will create a retain cycle as we saw previously the pop-up has a strong reference to the unsafe closure right while the on saved closure has a strong reference to the view controller as we can see with the self keyword inside the closure here and now this view controller has a strong reference back to the pop-up the memory graph has changed so let's take a look at what it looks like now as you can see now we have a nice little circle going around and around because now that view controller which is inside the closure has a reference back to the pop-up which is a strong reference and because of this we will have orphaned objects in memory also known as a memory leak swift can't remove the date pop up view controller and it can't remove the view controller because they both point to each other and because they both point to each other they will have a reference count that can never get to zero so Swift can't remove them so how are we going to fix this problem let me ask you something first if the closure is its own object how can we didn't have to pass in self as a parameter or how can we didn't have to pass it in as an argument like in a constructor the way other classes work how is this view controller actually getting into that object the closure the answer is what is known as capturing values capturing values what does that mean let's try to understand this concept swift calls capturing we need to know this because this is what's going to lead to the solution that will enable us to resolve the memory problem in Swift documentation it says a nested function can capture any of its outer functions arguments and can also capture any of its constants and variables defined within the outer function okay that's a lot to take in so what's a nested function and what's in outer function well let's look at an example see if we can sort this out okay we have another example here of a closure that is capturing the values around it the UI view animates trailing closure in this example is the nested function it's basically a function that's inside another function the do animation is the outer function so let's look at that statement again about capturing values a nested function which is the animates closure can capture any of its outer functions the do animation is the outer function can capture any of its arguments and can also capture any constants and variables defined within the outer function to do animation okay now I want to direct your attention to something here notice in the UI view animates function or closure it checks show label if show label so notice that the animates closure doesn't need self to reference the argument show label but it does need self to reference the label because it cannot capture my label without the self reference it can capture self but not the view controllers members outside of the outer function so that's capturing we don't have to pass in variables like arguments into nested functions we can just access them from the outer function it's also important to note that by default a closure captures values with a strong reference to those values if you're not sure what I mean by strong reference then you have to please watch the previous video the next question is can you pass in your own values into a closure the answer is yes in Swift you can do this with a capture list here's basic syntax with some examples the brackets indicate that the capture list is actually an array so you can pass in multiple variables into your closure as you can see you declared the variables normally we can instantiate value types as in the first example or instantiate reference types as in the second example so in our code we can do something like this here I create a label that represents self dot my label okay let's go into Xcode so you can see what it actually looks like okay run Xcode and this is just like the code example that we had before we're gonna create a CAPTCHA list okay and I'm going to create a label variable to represent self dot my label and then inside this closure I can just replace self dot my label with label okay just like that okay so you now know that you can use a cash list to create variables and pass them into your closure but there's one more thing you can do and that is you can change the strength of the variable in the CAPTCHA list by default variables coming in through the CAPTCHA list are a strong reference even if the variable is declared as weak such as this label it doesn't matter once it comes in through the capitalist it'll be a strong reference you can change us by using weak or unknown right in the CAPTCHA list and this is actually how you'll be fixing many retain cycles with this method right here let's look at the next example I create a variable BC to represent the view controller which is self and this is totally fine doing it this way but there's another way you can write this in capture list too instead we can just change the strength of the reference with unknown door week through the capture list like this and if you're unsure of like what we can unknown mean here then what you want to do is go back and watch the previous video part two where I describe strong weak and I owned basically the reason why I'm using unknown here is because I believe that self won't be nil when I get it okay now here we have the most common usage of the capture list we use it to pass in and change the reference strength of one of our captured variables from a strong reference to an unknown reference so using weak or unknown will break the retain cycle and will allow the pop-up and this view controller here to release themselves from memory so let's look at the memory graph here as you can see inside the capture list on the on save it's now an unknown reference and it breaks that cycle going around and around so at this point you might be wondering Shai Ali's use a capture list when using a closure uh you don't have to unless you have a retain cycle that you need to break capture lists do come with a little bit of overhead known performs slightly better than a weak reference but you'll probably never even notice it in most of your apps okay great with the knowledge you've gained from this series on memory you're now better equipped to see if you have retain cycles in your apps and then how to fix them using a capture list if necessary in the next video we're going to go back to the reasonable pop ups project I showed you three different ways of passing data back and forth each of those ways can create memory problems so that's what we're going to do we're going to create some memory problems and we're going to fix them too so subscribe and hit that Bell icon so you can get notified when that next video comes out because we're gonna go back into Xcode and we're going to apply this knowledge that you learned from these three videos if you liked this video give it a thumbs up feel free to share it with your friends on social media and if you'd like to help out you can also supply a translation to the title in the description all right thanks guys
Info
Channel: Mark Moeykens
Views: 14,532
Rating: 4.988935 out of 5
Keywords: Xcode, iOS, Programming, Swift, Tutorial, Tuts, Learning, Example, app, learn, make, how to, mobile, Xamarin, beginner, Closures, capture list, capturing, weak, unowned, [] in, memory leak, memory leaks, swift memory mastery series, swift memory, memory mastery, what is a capture list, Capture Lists and Strong Reference Cycles, closure syntax, Understanding memory leaks in closures, Most common memory leak trap in Swift, how to prevent, automatic reference counting, ARC, retain cycle, fast, code
Id: GIy-qnGLpHU
Channel Id: undefined
Length: 15min 47sec (947 seconds)
Published: Thu Jan 18 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.