
Among the projects we
are working on , perhaps, there is not one in which everything is in order with the memory. This post I will devote to the story of how to deal with this kind of problems.
Problems with memory include leaks and so-called "zombies". The application in which the memory mess is created becomes unstable, a whole bunch of oddities appear in it, starting with the disappearance of some interface elements and ending with crashes.
First, let's define what leaks are. Leaks are allocated but not freed areas of memory for which there is no pointer. All this looks quite serious, the iPhone has a lot of RAM, and the usual application takes at best 2 MB. In fact, everything is not so rosy: the application can use up to 3mb, and then memory warning starts to arise, respectively, the OS tries to free those areas that it considers "unnecessary." Simply put, it removes the currently invisible interface elements, and this is not only ugly, but can also cause the application to crash. “Zombies” are already freed (dead) areas of memory that the program is trying to access, which also causes the application to crash.
IOS has a garbage collector!
Many (yes, I myself also sin it) often say that it is not there. But still there is a garbage collector, albeit a very primitive one. The principle of memory management is based on counting the number of references to an object. When allocating memory for an object, their number is set to 1, and when it reaches 0, the memory is released (garbage is thrown). Every time you want to use an object, you have to increase the number of links, and every time it becomes unnecessary for you to reduce it.
')
There are 4 magic words
To manage memory, you need to remember only 4 words:
alloc
,
copy
,
retain
,
release
. Let's talk about each of them separately:
alloc
Allocates memory for an object and increases the number of references to 1. It is necessary to use it every time you create a new object.
copy
Copies an object (not a pointer). Leaves unchanged the number of links to the object that we copy and increases their number to a new object.
retain
It simply increases the number of references to the object.
release
The reverse of the three operations listed above reduces the number of references to 1.
And something else
Autorelease
This is a slightly different story. If you send an
autorelease
message to the object, a “delayed”
release
will occur. This is necessary for those cases where you cannot, for some reason, send a message to the
release
object after acting on it. Its main use is the return of objects by methods. Any method whose name does not
alloc
,
copy
,
retain
, returns, and must return a “authorization” object.
But why not use it everywhere? It's so convenient! Convenient, but expensive. Due to the fact that the number of references to an object is not immediately reduced, respectively, the memory is also not immediately released. Here we are waiting for the underwater stone: we have only 3mb, and if we are processing a large amount of data at once, the very same memory warning appears.
Dealloc
This method is called when an object is deleted, in it you have to release all the variables that the object used, and at the end call
dealloc
on the parent.
- (void)dealloc {
[model release];
[view release];
[super dealloc];
}
Property
Properties are of three types:
assign
,
retain
,
copy
. The last two should be clear. And the first simply assigns a value without affecting the number of references to the object. I will give the correct implementation of setters for each type:
//assign
- (void)setList:(List *)list{
_list = list;
}
//retain
- (void)setList:(List *)list{
[_list autorelease];
_list = [list retain];
}
//copy
- (void)setList:(List *)list{
[_list autorelease];
_list = [list copy];
}
Remember, you don’t need to keep track of what
Property
does; you just have to set it, and if necessary, reset the value, just reset it.
Delegate, chicken and egg
In the process, we stumbled upon a problem related to the fact that a large number of objects were leaking from us. It turned out that we had two objects that trailed each other and, accordingly, never freed up memory. This happened when using the delegation pattern. There was an object that created another object and set itself up as its delegate. And the
Delegate
property was spelled as
retain
. The situation is saved by replacing
retain
with
assign
.
Some last tips
- The word release should come immediately after
alloc
, retain
or copy
- And the word nil immediately after
release
- Always nil delegates
- If possible, refrain from
autorelease
- Create objects exactly when you need them.
- Do not abuse the class fields
- Static Analysys Tool draws everything nicely and clearly
- Check for leaks occasionally
Ivan Ushakov, iOS Team Programmer