0:00
[MUSIC]
In this lecture, what we're gonna talk about is ARC.
ARC at a high level is a way to help developers like
us to handle memory management better.
And one of the things that it emerged out of was a lot of legacy
from the C programming language that was brought into Objective-C.
Over time, some of the pitfalls that programmers ran into when they were
programming in C, particularly around memory management,
became such a pain to deal with that ARC was brought, that ARC was developed as
a technology within Xcode and Objective-C to help programmers do a little bit
better job of keeping track of memory and preventing memory leaks.
0:58
So among the many legacies of C is code syntax.
There's still quite a bit of code syntax left over from C style programming,
from the C language, and it still works in Objective-C.
You'll often see it in some of the existing code bases that are out there,
and maybe in examples on the Internet and it'll work.
But newer features have made a lot of these old techniques less attractive, and
we've talked about some of these C-style coding
conventions in this class because you're gonna run into them.
And also because it helps to understand the trajectory from where
newer code came from, so
you can understand what the development was and how we got to where we are.
2:07
Well, NSLog is kind of the evolution of printf for Objective-C.
And one of the things that it does is it acknowledges that programs today
aren't command line programs.
The majority of the things that are programmed
in the one that probably drew you to this course in the beginning, were apps.
Apps on smartphones, in particular, the Apple ecosystem, the iOS ecosystem.
There's no command line.
There's no console that a user sees at all.
And so talking about printing stuff out to the command line kinda doesn't make sense.
Even in the desktop or laptop environment, graphical user interfaces, or
GUIs, don't really have a command line output.
And so printf is sort of a legacy from a previous time a previous way of doing
computer programming.
3:45
A second legacy that we have from C is the char * type.
So char is a character.
Char is short for character, and star is a pointer to char.
And this was the way that strings were originally managed.
And if you recall from a previous lecture,
we talked about how when you created a string,
it set aside a little bit of memory and each bit of memory had a letter in it.
And it ended with a zero and
although character pointer just points to one moment, one spot in memory.
The interruption of that char * as a string had the computer walk through
memory until it got to a zero.
We didn't talk about it in this class, but if you don't have a zero at the end of
your string, the computer can just keep walking forever and
run all over memory and do all kinds of messy in many cases,
risky security wise kind of actions.
It's also just a pain to manage the memory associated with char *.
NSString is an evolution of the char * way of dealing with string.
NS * is much more naturally accommodates international characters.
When C was first developed, there really, international characters were really
an afterthought in computing and in a string incorporates a modern technology
such as unicode to represent all the characters in languages around the world.
It also doesn't you require you to think about where the characters
are being stored.
You don't have to think about memory that's all encapsulated within the object
and the object is responsible for managing that and all you do is work with
the interface, work with the method calls that it provides to get text in and out.
And if someday, that technology changes, doesn't matter as long as the interface
remains the same, you can continue to use your old code with the new technology.
You know what else?
And, of course you don't have to worry about that trailing 0.
A third example of legacy code is malloc, or memory allocation.
Malloc, we had one example earlier where we set aside a little bit of memory
on a heap in order to give a point or something to point two.
This was good it gave you manual control over heap space, but it was kind
of obnoxious because you had to figure out exactly how much heap space you needed.
And that could get a little tricky when you started working with structs and
started working with combinations of pointers and
maybe objects whose definition you didn't really know beforehand.
6:29
A final fourth legacy piece of code that I want to talk about from
the C language is free.
Free was the opposite of malloc if you remember.
When you reserved a piece of memory from the heap, if you didn't later free it,
it would stay forever reserved on the heap until your program ended.
And as your program ran,
if it didn't do a good job at getting rid of these chunks of memories,
the memory requirements in your program will grow and grow and grow over time.
And that's called a memory leak when you don't take care of your old memory,
don't allow it to be reclaimed.
7:01
So ARC is the modern trajectory,
the modern answer to the problem of having to malic in free memory.
ARC automatically reclaims heap space when it's not being use, and this is
a huge win because it greatly reduces the places in which you can have memory leaks.
Not entirely, but it does a really good job of hitting a majority of the cases.
So our old code from C that you may still use, but it's really not best
practices to use it going forward, are printf, char *, malloc, and free.
And then our new code going forward is gonna be NSLog, NSString, alloc, and ARC.
That's good but how does ARC actually work?
Well ARC is an acronym.
It stands for Automatic Reference Counting and
it's already turned on in your projects.
So it's turned on by default,
it's so useful that it's rare that anyone would want to turn it off.
So in order to understand what it is that it does,
let's go back to the days of Malkin free.
Let's imagine that you were a programmer and you had created a pointer.
And then you allocated some memory and
you stored a string in it, then you set your pointer equal to that string.
It's pretty easy to keep track of, one pointer, one string.
Maybe you have some data, you have a pointer you out malloc some data space,
you set your pointer equal to that data, no problem.
Pretty easy to keep track of that.
You're not gonna worry about having to free that memory,
it's clear that you that you need to free it up when you're done with it.
But real programs, you have tons and tons of data and
you probably have lots and lots of strings.
And you're interfacing with teams of people who are writing code.
And you're probably interfacing with libraries.
And pretty soon you have another pointer and that's pointing to a data object.
And now it's starting to get a little bit more tricky to remember how to
keep track of all these different items.
Another pointer comes along and now you have three pointer to the same data piece.
And now maybe you have an existing pointer and you want to go and you want to change
what it's pointing to and this keeps going over the life cycle of the program.
Not even a necessarily long program but
one that just has a complicated data structure.
And before long what was a very simple
process of just a few pieces of data that you were mallocing and freeing.
Becomes a nightmare of pointers all over the place,
you're not sure where the pointers are, you're not sure if they're yours,
you're not sure about the data.
What happens is you ended up with these chunks of data,
that were all over your heap space that didn't have anyone pointing to it, and
these were the leaks, these were the bits of memory that were getting left behind in
the complicated structures of a modern multi-person large program.
Preventing these memory leaks was a real hassle in the olden days, but today,
we live in the future.
9:46
One of the reasons why it was difficult was because when you got a pointer
back from a function call, for example, and that function allocated some memory.
And that when you got that pointer back to that memory,
it wasn't clear clear whether it was your responsibility or not to free that memory.
Was it your responsibility because you received it back?
Or was it the responsibility of the function or
the object that generated the chunk of heat memory to clear it?
Or maybe there was some other process by which that memory got freed.
Because that object that was being passed back as part of a life cycle,
that's supposed to go through a number of stages,
the last stage of which is supposed to free it.
That would be fine, but sometimes it was really hard to understand what
the other programmers, what the library programmers intended.
For the lifecycle of that object to be.
11:14
Anytime, you set a pointer equal to an object you would increment the counter and
everyone have the same counter for that object and
everyone had access to that counter.
And every time you moved a pointer off of an object to point to something else or
to set it equal to nil,
you would decrement the reference counter associated with that object.
So you knew, that if you were the one that decremented that reference counter and
it became zero, there was no one else, there was no other code in your library or
process that was pointing to that object, and
so it was your responsibility to free it.
That was kinda an answer to this confusing question of whose responsibility was it to
clear the pointer.
It was who ever set the reference counter equal to zero.
It was your responsibility.
Se here's kinda what it looked like.
You have one pointer, pointing to a piece of data,
and when you point it to it you'd set the reference counter equal to one, one count.
12:38
Changes the pointer, sees that the counter is 0, and
is responsible for freeing the object.
So that was great.
Now you didn't have to assign responsibility that point our object to
any particular person in the life cycle.
The object's memory management was a decentralized affair
it could be handled pretty well.
If the counter got to 0 it was your responsibility.
That was good, but it was bad because it still required programmers to remember
to do the counting.
If they forgot, then there was still a memory leak.
And believe it or not, even though it seemed really important, and
it seemed kind of straightforward, it was really hard for
the body of your code to remember to do this consistently and to do it well.
So enter ARC.
ARC, automated reference counting.
The way ARC works is it addresses this problem with having to remember
to do the counting and the uncounting.
15:06
Finally, in our third variable c we point at the same thing that a's pointing to and
now the retain count is 3 for the object that a points to that's set.
When we set b equal to nil the retain count goes down to 2 and
when we set c equal to no the retain count goes back down to 1 because
a is the only thing that points to it.
And if we were to set a equal to nil at this point, ARC would automatically
clear the memory that had been allocated in the first line of that code.
It's really a great timesaver, relieves a whole range of concerns
from the programmers mind that they don't have to think about any longer.
15:43
Turns out you can't totally ignore memory management.
There's a couple examples that we'll look at in a future lecture
about blocks that you have to watch for.
But it certainly has relieved a lot of pressure.
So in summary, ARC is a system that helps with memory management.
It allows programmers to think less about freeing memory.
And instead, if you ever want to make sure your memory gets freed, all you have to do
is set a pointer equal to nil if you want to explicitly release memory.
And actually it's a pretty good practice, whenever you're done with a pointer
rather then just leaving it pointing to some object In the heap.
Setting an equal to nil is a good way to prompt ARC to delete things that
may otherwise take awhile for the retain count to go down to zero.
It's also a way of explicitly making clear what your intents are so
other programmers can see that in your code even if it's not technically
necessary from a syntactic point of view or from a logical point of view.
Great, we'll look at this again when we talk about blocks, thanks.
[MUSIC]