This workshop will be retired on May 31, 2020.
Objective-C ARC6:49 with Gabe Nadel
Automatic Reference Counting (ARC) was a boon for developers, though there are still memory considerations you'll need to make. Let's explore the topics of memory directives as well as some common pitfalls like retain cycles and handling memory when using blocks.
So, the first thing to know about writing Objective-C under ARC 0:00 is that 95% of your code doesn't change. 0:03 The parts that do change, no longer needing to write all those retains, 0:06 releases, and the like, will make your life much easier. 0:10 Syntactically speaking, it's a boon for developers. 0:13 The second thing to understand is that just because the reference 0:16 counting is happening automatically, 0:19 doesn't mean you're immune to memory management problems. 0:21 You still need to write code that considers memory issues, and 0:24 also know how to track down memory related problems when they arise. 0:27 Tracking down and prosecuting memory issues is something we'll talk about 0:31 a couple of videos from now. 0:35 But first, let's talk about the memory directives, 0:36 which will ultimately determine how efficient your code will be. 0:39 So depending on what code you hacked on independently, 0:43 you may have typed many lines that look something like this. 0:46 That's a pretty standard property declaration you'd find in a .h file or 0:50 at the top of an implementation file. 0:53 Depending on how curious you are, 0:56 you may have dug into what all those things actually do, 0:57 though don't be embarrassed if you just typed it out without thinking about it. 1:00 Lots of developers do just that, and now's the time to see what's really happening. 1:03 Now, nonatomic specifies how different processes in a multi-threaded app 1:08 can interact with a property. 1:13 Chances are, at this point in your journey, your apps aren't multi-threaded, 1:15 so you can simply type nonatomic each time and move on. 1:18 Great. One less thing to think about. 1:22 If you did wanna make sure your property was thread safe, 1:24 you would use the attribute atomic instead of nonatomic. 1:27 If you'd like to learn a little bit more about what multithreading is and 1:31 how this works, please check the links below. 1:34 Strong, on the other hand, is a memory directive. 1:36 This memory-directive determines when we increase an object's reference count and 1:39 when memory can be released. 1:44 Now, strong is just one of the options you have, but 1:46 it's the most common one you'll see. 1:49 It's also the same as retain, 1:51 which you would see in pre-ARC property declarations. 1:53 Simply put, strong means that the reference count will be increased, and 1:56 the reference to it will be maintained throughout the life of the object. 2:00 When the count reaches zero, the memory can be released. 2:05 Let's take a minute to go through the other memory directives you'll need to be 2:08 familiar with. 2:11 Weak means that we're pointing to an object but 2:13 not increasing its reference count. 2:16 It's often used when creating a parent child relationship. 2:18 The parent has a strong reference to the child, but 2:21 the child only has a weak reference to the parent. 2:24 Read-only means just what it says. 2:26 You can set the property initially, but then it can't be changed. 2:29 This could come in handy for all sorts of stuff you don't want changed accidentally, 2:33 ever, for instance, a userID number. 2:37 Copy makes a copy of the object to be referenced. 2:40 It then points to the copy instead and sets its reference count to 1. 2:43 Using copy means that we are copying the value of the object when it is created. 2:48 This prevents its value from changing if the value of an object it's pointed to 2:54 changes. 2:58 Let's us say we have a class called Car. 3:00 In that class, we declare two properties. 3:02 Later, we create an instance of the Car like so, and 3:05 create another NSMutable string like this, and 3:09 then set our properties to that new variable model like this. 3:14 Well, at this point, we know both of our properties have a value of Fiat Spyder. 3:19 Now, let's change the value of model like this. 3:24 Now if we check both values, we'll see that there, you see the strong value 3:28 has taken on the new value of the object it was referenced to. 3:32 However, the copy has not. 3:36 It will keep the value it had when it was first created. 3:38 You can see how this could have far-reaching implications in a piece 3:41 of software. 3:44 Now, if all of this sounds strikingly familiar, 3:45 like the difference between value types and reference types in Swift, that's good. 3:48 The same principles are at work here. 3:53 Now, Objective-C has a superset of C, is strictly speaking, 3:54 a passed by value language. 3:59 However, and this is an important however, since we so often use pointers in 4:01 Objective-C, our code can behave as if it were passed by reference. 4:05 You see, if that value that you're copying is itself a reference, 4:10 then you've managed to get your code to act on changes to that reference. 4:15 If we couldn't do that, it would be very hard to do lots of the things we've come 4:19 to rely on when we built Objective-C software. 4:23 Before we move on to Swift Memory Management and 4:26 troubleshooting memory problems, 4:28 let's touch on one Objective-C memory wrinkle surrounding the topic of blocks. 4:30 So when we say blocks here, we don´t just mean any old section of 4:35 code which someone might casually refer to as a block of code. 4:39 What we´re talking about is the Objective-C analog to closures in Swift or 4:43 lambdas in other languages. 4:47 Blocks are a topic all their own and 4:49 one worth familiarizing yourself with, but we'll just give a brief description for 4:51 the purposes of talking about memory management. 4:55 So when we say blocks, we're talking about these. 4:57 Now of course, that's an unrealistically simple example, but 5:01 this may jog your memory as to when you've been off in the wild and encountered 5:04 a strange creature being led around by a carrot and trapped within curly braces. 5:07 Without going too in depth, blocks are extremely useful 5:12 because they're chunks of code that we can pass around as arguments to methods or 5:15 functions, or even use them in lieu of a function. 5:19 They also have very handy feature, whereby they capture the instance variables 5:22 which are in scope at the time the block is invoked. 5:26 This means that you could invoke a block, 5:29 pass it to a whole series of other objects, one after the other, and 5:31 the instance variables will go along for the ride. 5:35 When used correctly, they're a total game changer. 5:38 But selling you on blocks isn't the point. 5:41 The point is to highlight that blocks are particularly prone to retain cycles. 5:43 In case you don't remember, a retain cycle is where x is holding onto y, and 5:48 y is holding onto x, but no other objects care about either x or y anymore. 5:52 But you still can't release them, because they're holding onto each other. 5:58 It's like the scene at the end of the movie where the lovers would sooner 6:02 die than break their embrace, except in this case, 6:04 it's your code that's going down in flames. 6:07 What's more, it can be very hard to trace these problems when they arise. 6:10 A retain cycle involving something small like some strings or numbers 6:14 may not cause noticeable performance problems, but if you use the same code to 6:18 handle heavier items, like audio clips or big objects, it might cause a crash. 6:22 We aren't gonna get into the code level examples surrounding block retain cycles, 6:28 but you should know that if you're experiencing tough to trace memory issues, 6:32 a good thing to look at is how your blocks are structured, and 6:36 where appropriate, explicitly use weak references to prevent retain cycles. 6:39 If you'd like a more in-depth discussion, 6:44 there's a great article linked in the teacher's notes. 6:46
You need to sign up for Treehouse in order to download course files.Sign up