This workshop will be retired on May 31, 2020.
Leaks9:35 with Josh Timonen
We want to ensure that no memory is getting leaked out, and in order to check for leaks, we will need to run this app in Instruments.
- A “leak” is when memory has been allocated for something, and then the system is unable to reclaim and reuse it.
- ARC: Automatic Reference Counting
Mac Developer Library: Instruments User Guide
We're going to look at how instruments can help identify memory leaks in your iOS and 0:00 Mac applications. 0:04 Memory management has become much simpler thanks to Automatic Reference Counting, 0:06 commonly known as ARC, but there are still cases where leaks can occur. 0:10 Technically, a leak is when memory has been allocated for 0:15 something and then the system is unable to reclaim and reuse it. 0:17 So we want to ensure no memory is getting leaked out. 0:21 We want everything to be properly reclaimed by the system. 0:24 Let's jump into our demo project. 0:28 Open the Instruments demo Xcode project included with this workshop. 0:30 Let's go ahead and run it in the simulator. 0:35 As you can see, it's a fairly simple app with a route view controller that contains 0:41 a table view and when you tap each row, 0:46 it loads a simple view controller with an image and a number. 0:48 In order to check for leaks, we'll need to run this app in Instruments. 0:52 Since we've already installed the app into the simulator, 0:56 one way to test it would be to launch Instruments on its own. 0:59 I generally do this by using the Alt+Space hot key combination and 1:02 typing instruments, then Enter. 1:05 You can also launch it through Xcode's main menu drop-down selecting 1:08 Open Developer Tool > Instruments. 1:12 You should see Instruments' profiling template selection menu but if you don't, 1:15 go to File > New from its main menu. 1:20 We'll be working with the Leaks template. 1:23 Select that, then hit the Choose button. 1:25 If you come into Instruments through this path, 1:28 you'll want to be sure that you select the device and 1:31 application from the top left menu next to the record and pause controls. 1:33 Here we see that the iPhone 6s 9.3 simulator is selected for the device. 1:37 If we're testing in the simulator, 1:43 be sure we're testing the same simulator we built too through X code. 1:45 We want to be sure we have the accurate version of our app. 1:49 Then, in the menu to the right of the device, 1:52 we can select from the list of installed apps. 1:55 We'll be testing this Instruments' example app. 1:57 Hit the record button, and the app is launched in the simulator. 2:00 We can see the allocations and 2:07 leaks data are both coming in on the timeline in Instruments. 2:09 Great. But let's hit stop and 2:12 see a quicker way to get into this Leaks tool. 2:15 Let's go back to Xcode, then run the app in the simulator there. 2:20 Select the debug navigator in the left column, then memory in that menu. 2:30 As you can see, Xcode gives us a memory usage information 2:35 right here without us having to launch instruments which is nice. 2:38 You can watch your app's memory footprint change over time, see percentage of memory 2:42 use and a comparison to other processes on the device. 2:47 We are running this workshop against the iPhone simulator which will work for 2:50 our example but in general it's best to run memory in performance testing against 2:54 a real physical device. 2:59 The simulator has access to the resources of your computer 3:00 which are probably much greater than on an iPhone or iPad. 3:04 So here's how we could launch our running app session from Xcode directly 3:07 into Instruments. 3:11 We'll select Profile in Instruments in the top right of the main window. 3:12 Then hit Transfer and the app session is now running in Instruments. 3:16 This opens up the Leaks template which includes a memory 3:20 allocation instrument at the top and a leaks instrument below that. 3:23 This workflow from Xcode into Instruments is really nice 3:28 because it ensures you're always testing your latest code changes. 3:31 If we just sit here, we'll see that the leaks instrument is displaying green 3:35 diamonds with check marks in them indicating that no leaks were found. 3:39 If you highlight over the check mark, you'll see that it says no leaks. 3:43 Let's pause for a second. 3:53 In the next step, we're going to scroll up and 3:56 down in the table view in the simulator and see what happens. 3:58 So lets unpause and go over to the simulator. 4:01 We can see that we are getting red diamonds with Xs in them. 4:19 If we mouse over the X, we see it says a number of new leaks. 4:23 First let's pause and look at the numbers. 4:27 Select the leaks instrument in the top timeline. 4:32 In the lower details panel, we can see the leaks by backtrace 4:36 which displays all of the objects that were leaked. 4:40 We can see that our THRose and THJack objects are the culprits. 4:43 Let's click the expand arrow to the left of the THJack row at the top of the list, 4:49 which will show us all ten instances of this object that leaked, 4:54 each with a specific memory address. 4:57 The far right column says the responsible frame was the THRoses init method. 5:00 If we double tap this row, 5:06 we can see specifically where this happened in our code. 5:08 We can see that this THJack instance is being created in THRoses' init method. 5:11 We'll have a look at our code in just a second. 5:17 At the top of the details window, select Cycles & Routes from the drop-down menu. 5:19 Here we can see all of the Leak Cycles that instruments has identified 5:25 during our run. 5:29 As we can see, we have a whole list of cycles. 5:30 They all say 2 nodes and under Details, it says Simple Cycle. 5:33 To the right, we see a nice little diagram showing that THRose is holding on to 5:38 THJack which in turn is holding on to THRose. 5:42 Never let go, Jack. 5:46 Boy. 5:49 Well, Jack needs to let go of Rose, at least in this workshop or 5:50 else our app is going to keep leaking, and you know what that means. 5:55 This code pattern is what we call a retained cycle and it's bad. 5:59 Both objects are holding onto each other with a strong reference and so 6:04 the system isn't able to release them. 6:07 This is generally something that we've done by accident. 6:10 We want to keep our strong references going in one direction between objects to 6:12 signify ownership, and 6:16 then use weak references when one object doesn't need to own something. 6:19 You can also tap the arrow to the right of the type column to see a diagram, which in 6:23 this case is just a simple line showing that both are holding onto each other. 6:27 Since we know the responsible frame is THRoses' init method, 6:32 let's head over to Xcode and have a look at the code. 6:37 Let's switch to Leaks in the drop-down menu at the top of the detail panel, 6:39 then double-click the first line. 6:44 This, again, shows us the code sample and we can click on the Xcode icon in the top 6:46 right of the detail window to launch Xcode and that shows us the relevant code. 6:50 We can see that Jack's initialization takes a variable in initWithRose 6:56 which passes in self. 7:00 Let's command click on the method here to open its implementation. 7:02 We can see that Rose is getting set on Jack as a property. 7:06 Let's look at the interface in the .H file. 7:10 So here we can see that we're creating a strong reference to Rose. 7:15 Let's have a look at Rose's interface. 7:19 We can see that Jack is held with a strong reference on Rose and that's our problem. 7:27 Both objects are holding onto each other with strong references. 7:32 If we look at our THViewController.m file in itself for row and index path method, 7:36 We can see that we are creating a new instance of Rose each time the method 7:46 is called and we Venda THTitanic cell. 7:50 If we look at the .h file for THTitanic's cell, 7:55 we can see that Rose is a strong property on the cell. 7:58 So each time the cell is reused, it's trying to de-allocate the old rows and 8:04 its subproperties and it's failing because of the retained cycle. 8:08 To solve this, let's go to THJacks.h file. 8:13 We want change the rose property to be a weak reference instead of strong. 8:17 This means that Jack is not going to increase Rose's retained count in ark and 8:22 expect something else to hold on to Rose. 8:27 In this case, that will be the THTitanic cell which has a strong reference to Rose. 8:30 Let's relaunch the app, then send it back over to Instruments through the debug 8:37 navigator and the memory window. 8:41 We'll transfer the session as before and 8:49 then start scrolling once we're transferred. 8:51 We'll see that we're getting green diamonds with checks now. 9:01 No more leaks. 9:03 Great. 9:05 Running the Leaks tool in Instruments is a good way to make sure you're writing code 9:08 that behaves properly under ark. 9:12 But it's important to remember that some memory issues may not show as leaks. 9:14 It's good to check your memory footprint with the allocations tool as well 9:19 to find issues with memory that may not be technically leaking but 9:23 may just be held onto longer than desired. 9:26 See the Introduction to Instruments and Allocations Workshop for more information. 9:30 Thanks for watching. 9:34
You need to sign up for Treehouse in order to download course files.Sign up