In-depth analysisObjective-C memoryThe management tutorial is the content to be introduced in this article. In the iPhone SystemObjective-C memoryThe management mechanism is flexible, that is, it can be used like C/C ++, or an AutoreleasePool can be added to upgrade it to semi-automatedMemoryManagement language. Of course, it cannot be compared with fully automated GC in the Java Virtual Machine.
Reference count is the only reference for memory collection of instance objects
Reference count (retainCount) isObjective-CThe unique basis for Object Reference Management. 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.
Main Operation interfaces:
1. alloc, allocWithZone, new (with initialization)
Allocate memory for the object, retainCount is "1", and return this instance
2. retain
- RetainCount plus "1"
3. release
The dealloc method of this object is called when retainCount minus "1" and is reduced to "0"
4. copy and 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. Because of its introduction, the Objective-C non-GC management environment is upgraded from full manual memory management to semi-automation.
- - (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.
Array) is a special example when you add an object to the Array. What is stored in the array is not a copy of the object, but a pointer to the object. When the array saves the pointer, it will send a retain message to the object indicated by the pointer. Correspondingly, the holding count of the object will increase. When the object is removed from the array, the release message is also sent to the object, and the holding count of the object is reduced. When the array is released, the release message is sent to all objects in the array. Let's look at the two examples below:
1. No memory version is released
- array = [[NSMutableArray alloc] init];
- for ( i = 0; i < 10; i++) {
- newNumber = [[NSNumber alloc]initWithInt:(i * 3)];
- [array addObject:newNumber];
- }
When creating a newNumber object, the code above sends a retain message to the object, and the hold count of the object changes to 1. When the reference of this object is added to the array, a retain message is sent to the object, so that the object's Hold count is changed to 2. When array is used up, we will habitually release the array, but this will not release the objects held by the array, but only change the Hold count of all objects to 1, these objects will still occupy the memory.
2. Release the memory version
- for (i = 0; i < 10; i++) {
- newNumber = [[NSNumber alloc]initWithInt:(i*3)];
- [array addObject:newNumber];
- [newNumber release];
- }
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:
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- int retVal = UIApplicationMain(argc, argv, nil, nil);
- [pool release];
We first regard the pool as a common object ~ 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 assumes that no other AutoreleasePool instance is declared in the middle of the Code in all segments. 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 release it here once because we only autorelease once)
For the same instance, the same Pool can be registered multiple times. In a few situations, this requirement may occur:
Code:
- NSAutoreleasePool *pool = [[NSAutoreleasePool 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:
- NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
- NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
- NSAutoreleasePool *pool3 = [[NSAutoreleasePool 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 the release operation is not always performed when we execute the autorelease method ~ 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.
Summary: in-depth analysisObjective-C memoryI hope this article will help you with the introduction of the management tutorial!