I have written a similar article before. I want to help my new brother. Pai_^
The objective-C memory management mechanism in the iPhone system is flexible, that is, it can be used like C/C ++, you can also add an autoreleasepool to upgrade it to a semi-automated memory management language. Of course, it cannot be compared with fully automated GC in the Java Virtual Machine 〜
I. Reference count is the only reference for memory collection of instance objects
Retaincount is the only basis for objective-C to manage object references. After the instance's release method is called, this attribute is reduced by one. The dealloc method of the object to zero is automatically called to recycle the memory. That is to say, we should never manually call the dealloc method of the object.
Its memory management API is simple and easy to use. below is its main operation interface:
1, alloc, allocwithzone, new (with initialization)
Allocate memory for the object, retaincount is "1", and return this instance
2, release
The dealloc method of this object is called when retaincount minus "1" and is reduced to "0"
3, retain
Retaincount plus "1"
4, copy, mutablecopy
Copy an instance. If the number of retaincount is "1", this instance is returned. The obtained object is independent of other contexts (Clean object ).
5, autorelease
Add this object to the autoreleasepool instance at the top of the autoreleasepool stack in the current context. As a result, the introduction of this object increases objective-C (non-GC management environment) from full manual memory management to semi-automation.
Ii. Objective-C memory management principles
We can classify the above interface into two types based on the Operation nature of retaincount,
Class A is a plus-one operation: 1, 3, 4
Class B: 1 minus operation: (delayed release)
The memory management principles are as follows:
1. The number of calls of Class A and Class B must be in the same format.
2. In order to ensure the good principle 1, the instance object is taken as the unit, and whoever has a is B, no two participate.
Code:
- NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
- Nsobject * o = [[nsobject alloc] init]; // retaincount is 1
- [O retain]; // retaincount is 2
- [O release]; // retaincount is 1
- [O autorelease]; // retaincount is 1
- [Pool release]; // The value of retaincount is 0, triggering the dealloc Method
3. Object owner
In the Object-Oriented field, there is a reference concept. Unlike inheritance, references are often used as designs with lower coupling. Inheritance is strongly dependent, right. To reduce the design of the software, we need to minimize the use of the software. However, it is useless to have no coupling modules or functions ~ Right, so we can only use more references. When an instance has another instance, we call it a reference to another instance.
For example, the setter method of an attribute object in the classa class:
Code:
- -(Void) setmyarray :( nsmutablearray *) newarray {
- If (myarray! = Newarray ){
- [Myarray release];
- Myarray = [newarray retain];
- }
- }
Assume that an instance of this class is 'A'. After setmyarray is called, we can say that a has a new myarray instance, or a references a new myarray instance. The retain method is called to add one to the retaincount of myarray. Note the following two points:
1. In the setmyarray method, the old instance is release once before retain.
2. In the dealloc method of this instance, the current instance should be release again, but let's look back at the memory management guidelines. It's not reasonable, right... There is one more release. Here, we recommend that you:
[Myarray setmyarray: Nil];
In this way, the current instance release can be cleverly enabled without errors (we can send messages to nil ~ In fact, it is an integer 0) and complies with our memory management rules. What's more, it's very simple. You don't need to think too much about it.
Another one is easy to ignore and
The classic problem is the circular reference of instance variables. Objective-C distinguishes between them, which is actually quite simple:
1. Strong references. The above section describes strong references. There is retaincount plus one.
2. Weak references. However, any assign declared and directly implemented using pointer assignment is called a weak reference. There is no retaincount plus one.
4. autoreleasepool makes objective-C a semi-automated language for memory management.
If it's just the above, it's easy, right. However, many people tend to be confused about Automatic Memory Management. It seems like magic, but the principle is also very simple 〜
First look at the most classic program entry program:
NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
Int retval = uiapplicationmain (argc, argv, nil, nil );
[Pool release];
Let's first regard the pool as a common object ~ Very simple. First, alloc, and pool retaincount is 1. In the third statement, release, retaincount is 0, and its dealloc method is automatically called. It is no different from any other common object.
Where is magic?
After the pool is declared, the previous Code of release, the Code in all segments (assuming that no other autoreleasepool instance is declared in the middle), all instances that call the autorelase method, retaincount is added to 1, and the record to be recycled is added to this pool instance for record filing. When this pool instance is dealloc, it first checks all the instances that have been filed for record, and all the recorded instances call its release method in sequence.
Code:
- NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
- Nsobject * o = [[nsobject alloc] init];
- [O autorelease]; // when the pool instance is dealloc, release this instance once. It is important not to release the instance in this row.
- Nslog (@ "O retaincount: % d", [O retaincount]); // at this time, we can see that our o instance is still available, and retaincount is 1
- [Pool release]; // The pool retaincount is 0, and the dealloc method is automatically called. Our previously filed minor o will also be release once here (because we previously only autorelease once)
For the same instance, the same pool can be registered multiple times. In a few situations, this requirement may occur:
Code:
- NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init];
- Nsobject * o = [[nsobject alloc] init];
- [O retain];
- [O autorelease];
- [O autorelease];
- [Pool release];
We have called Class A twice (the retaincount plus 1 method) to set its retaincount to 2, and the next two autorelease method calls, it has been registered twice in the pool. Here, the pool will call the two release methods of this instance when recycling. Reduce the retaincount value to 0 to recycle the memory. In fact, this is also a benefit of working in full accordance with the memory management rules 〜
Autoreleasepool is nested!
The pool is nested, And the nested result is a stack. The same thread is available only for the top pool instance of the current stack:
| Pool_3 |
| --------- |
| Pool_2 |
| --------- |
| Pool_1 |
| _______ |
The Code is as follows:
Code:
- NSAID utoreleasepool * pool1 = [[NSAID utoreleasepool alloc] init];
- NSAID utoreleasepool * pool2 = [[NSAID utoreleasepool alloc] init];
- NSAID utoreleasepool * pool3 = [[NSAID utoreleasepool alloc] init];
- Nsobject * o = [[nsobject alloc] init] autorelease];
- [Pool3 release];
- [Pool2 release];
- [Pool1 release];
We can see that the top of the stack is pool3, and O's autorelease is to manage the current release in the pool instance on the top of the stack... That is, pool3.
When the life cycle is short and a large number of instances are managed in the autoreleasepool, this method is often used to reduce memory usage and achieve timely memory recovery.
Where is autoreleasepool used?
In the above example, we can also see that when we execute the autorelease method, we do not always perform the release operation ~ its release is delayed to the dealloc method of the pool instance. This small detail allows our objective-C to apply for heap memory in the method stack, create an instance, and put it in the current pool to postpone the release of callers of this method 〜
The above is the memory management summary that I have come up with ~~~~ that's all about it ~ I am enough for daily work ~ I didn't expect you to add 〜