Objective-C magic path [17-memory management], objective-c17-
Master haomeng is devoted to his contribution and respects the author's Labor achievements. Do not repost them.
If the article is helpful to you, you are welcome to donate to the author, support haomeng master, the amount of donation is free, focusing on your mind ^_^
I want to donate: Click to donate
Cocos2d-X source code download: point I send
Memory Management is concerned with cleaning (recycling) unnecessary memory so that the memory can be reused.
There are three basic memory management models provided to Objective-C programmers:
1) automatic garbage collection. (The iOS runtime environment does not support garbage collection. This option is not available when developing programs on this platform. It can only be used in Mac OS X programs. This mechanism is quite disgusting. People on mac computers know that when the memory is insufficient, the machine is basically stuck .)
2) manually reference the count and automatically release the pool. (This method has high requirements on programmers. Self-maintenance ,)
3) automatic reference count (ARC ).
Objective-C provides an internal counter for each object, which tracks the number of times the object is referenced. All classes inherit from NSObject objects.
Retain and release methods:
When an object is created or copied, the reference count is 1. Each time an object is maintained, a retain message is sent to add 1 to its reference count. If this object is not required, a release message is sent to reduce the reference count by 1.
When the reference count of an object is 0, the system will know that this object is no longer needed and its memory will be released.
An object can be created by allocating memory or copy through alloc. The related methods include: alloc, allocWithZone: copy, copyWithZone, mutableCopy, mutableCopyWithZone, these methods can set the reference count to 1, and retain will add 1 to the reference count,
Release will reduce the reference count by 1.
Override dealloc Method
When an object contains other objects, you must release them in dealloc.
# Import <Foundation/Foundation. h> @ interface Song: NSObject {NSString * title; NSString * artist; long int duration;} // operation method-(void) start;-(void) stop; -(void) seek :( long int) time; // Method for accessing member variables @ property NSString * title; @ property NSString * artist; @ property (readwrite) long int duration; // constructor-(Song *) initWithTitle: (NSString *) title andArtist: (NSString *) artist andDuration :( long int) duration; @ end
The implementation is as follows:
# Import "Song. h "@ implementation Song @ synthesize title; @ synthesize artist; @ synthesize duration; // constructor-(Song *) initWithTitle: (NSString *) newTitle andArtist: (NSString *) newArtist andDuration :( long int) newDuration {self = [super init]; if (self) {self. title = newTitle; self. artist = newArtist; self. duration = newDuration;} return self;}-(void) start {// start playing}-(void) stop {// stop playing}-(void) seek :( long int) time {// skip time}-(void) dealloc {NSLog (@ "Release Song object... "); [title release]; [artist release]; [super dealloc];} @ end
Main function called
# Import <Foundation/Foundation. h> # import "Song. h "int main (int argc, const char * argv []) {Song * song1 = [[Song alloc] initWithTitle: @" Big World "andArtist: @" Oscar. emilia "andDuration: 180]; Song * song2 = [[Song alloc] initWithTitle: @" It's OK "andArtist: @" atomic kitten "andDuration: 280]; // print current counts NSLog (@ "song 1 retain count: % I", [song1 retainCount]); NSLog (@ "song 2 retain count: % I ", [song2 retainCount]); // increment them [song1 retain]; // 2 [song1 retain]; // 3 [song2 retain]; // 2 // print current counts NSLog (@ "song 1 retain count: % I", [song1 retainCount]); NSLog (@ "song 2 retain count: % I ", [song2 retainCount]); // decrement [song1 release]; // 2 [song2 release]; // 1 // print current counts NSLog (@ "song 1 retain count: % I ", [song1 retainCount]); NSLog (@" song 2 retain count: % I ", [song2 retainCount]); // release them until they dealloc themselves [song1 release]; // 1 [song1 release]; // 0 [song2 release]; // 0 return 0 ;}
Code Analysis: In this main function, two Song objects are declared. When the retain call increases the reference count, the release call reduces it. Call [obj retainCount] to obtain the int value of the reference count. When retainCount reaches 0, both objects call dealloc, so we can see that two "Release Song objects..." are printed ...". When a Song object is released, release its own object type member variables title and artist before calling [super dealloc].
Auto Release pool
The memory release pool provides an object container. Each time an object sends an Autorelease message, the reference count of the object does not change, but adds a record to the memory release pool, write down this requirement of the object until when the memory release pool sends a drain or release message, all objects in the pool will be notified before the pool is destroyed. Sending all the release messages will actually reduce the reference count.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];… …[pool release];// [pool drain];
These statements must be placed between the following statements until the pool is released. To include an object in the memory release pool, you must send autorelease.
# Import <Foundation/Foundation. h> int main (int argc, const char * argv []) {nutoreleasepool * pool = [[nutoreleasepool alloc] init]; NSArray * weeksNames1 = [NSArray arrayWithObjects: @ "Monday", @ "Tuesday", @ "Wednesday", @ "Thursday", @ "Saturday", @ "Sunday", nil]; NSArray * weeksNames2 = [[NSArray alloc] initWithObjects: @ "Monday", @ "Tuesday", @ "Wednesday", @ "Thursday", @ "Friday ", @ "Saturday", @ "Sunday", nil]; // [weeksNames1 release]; // [weeksNames1 autorelease]; // [weeksNames2 release]; // [weeksNames2 autorelease]; NSLog (@ "retain count: % I", [weeksNames1 retainCount]); NSLog (@ "retain count: % I ", [weeksNames2 retainCount]); [pool release]; return 0 ;}
The NSArray class is an unchangeable array class provided by the Foundation framework,
There are two types of methods for creating objects in the Foundation framework: class method (+) constructor and instance method (-) constructor.
Open the NSArray ClassReference document and create object-related methods.
From the NSArray Class Reference document, we can see that the Class-level constructor is a Class-level constructor that starts with "+" and "Class name" (removes NS, and contains 1st lower-case letters, array, the instance constructor starts with "-" and "initWith.
The class-level constructor cannot use release, and can be automatically included in the memory release pool management without the need for autorelease.
Instance construction method. If a release message is sent, the object will be released immediately. If an autorelease message is sent, the object will be automatically included in the memory release pool and will not be released immediately.
In iOS development, because the memory is relatively small, the object is basically instantiated using the instance construction method, and the object memory is immediately released by sending the release message.
Memory management parameters in properties
Sometimes, when we declare objects to be called across objects, memory management becomes more complex.
For example, there is a method for accessing member variables in the Song class. Of course, you can encapsulate them into attributes and manage the memory through attribute parameters.
In the Song class, set member variables as follows:
- (void) setTitle:(NSString *) newTitle {title = newTitle;}- (void) setArtist:(NSString *) newArtist {artist = newArtist;}
This Code actually has memory leakage. When a new Title is set, title = newTitle only changes the pointer and the old object is not released. Therefore, we will modify these methods as follows:
- (void) setTitle:(NSString *) newTitle {[newTitle retain];[title release];title = [[NSString alloc] initWithString: newTitle];}- (void) setArtist:(NSString *) newArtist {[newArtist retain];[artist release];artist = [[NSString alloc] initWithString: newArtist];}
First, retain the new object, release the old object, and then use the instance constructor to create a new object. Do not release the newTitle parameter in the method. Because the basic data type (non-object type) does not need to be released, the following statement is correct.
- (void) setDuration:(long int) newDuration {duration = newDuration;}
In addition, you must pay attention to the constructor. Instead of assigning title = newTitle directly, you must call your own setting method:
// Constructor-(Song *) initWithTitle: (NSString *) newTitle andArtist: (NSString *) newArtist andDuration :( long int) newDuration {self = [super init]; if (self) {[self setTitle: newTitle]; [self setArtist: newArtist]; [self setDuration: newDuration];} return self ;}
Assign Parameter
The assign parameter indicates that the value is directly assigned during the setting, instead of copying or retaining it. This mechanism is very suitable for some basic types, such as NSInteger and CGFloat, or types that you do not want to directly own, such as delegation.
Assign is equivalent to the following statement.
- (void) setTitle:(NSString *) newTitle {title = newTitle;}
Retain Parameter
The retain parameter retains the new value (send a retain message) when assigning values ). This attribute can only be used for the Objective-C object type, but not for the basic data type or Core Foundation. Retain is equivalent to the following statement:
(void) setTitle:(NSString *) newTitle {[newTitle retain];[title release];title = [[NSString alloc] initWithString: newTitle];}
Copy Parameters
Copy Copies a new value when assigning a value. The copy operation is executed by the copy method. This attribute is only valid for objects that implement the NSCopying protocol. Copy is equivalent to the following statement:
- (void) setTitle:(NSString *) newTitle {[newTitle copy];[title release];title = [[NSString alloc] initWithString: newTitle];}
Summary of manual memory management rules:
1) If you want to keep an object from being destroyed, you can use retain. After using the object, you need to use release to release it.
2) Sending a release message to an object does not have to destroy this object. The object will be destroyed only when the reference count of this object is reduced to 0. The system then sends the dealloc message to the object to release its memory.
3) to release any object that uses the retain, copy, mutableCopy, alloc, or new method, and attributes with the retain and copy features, override the dealloc method, this allows you to release instance variables when an object is released.
4) when the automatic release pool is cleared, some things will also be done for the automatically released object. Each time the system sends a release message to each object in the pool when the pool is released automatically. If the object reference count in the pool is reduced to 0, the system will send the dealloc message to destroy the object.
5) if you no longer need this object in the method, but you need to return it, you can send the autorelease message to this object to mark the delayed release of this object. The autorelease message does not affect the reference count of the object.
6) when the application is terminated, all objects in the memory will be released, whether or not they are in the automatic release pool.
7) when developing a Cocoa or iOS application, the automatically released pool is created and cleared as the application runs (each event occurs ). In this case, if the object to be automatically released after the automatic release pool is cleared still exists, the retain method must be used for the object, as long as the reference count of these objects is greater than the number of autorelease messages sent, the objects can survive after the pool is cleared.
Automatic Reference count (ARC ):
Strong variables. Generally, pointer variables of all objects are strong variables.
To declare a strong variable, use _ strong Faction * fl; to modify it.
It is worth noting that the default attribute is not strong, and its default feature is unsafe_unretained similar to assign.
When you need to declare the attribute strong, you can:
@ Property (strong, nonatomic) NSMutableArray * birdNames;
The compiler will ensure that the strong attribute can survive by executing the value assignment in the event loop.
Attributes With unsafe_unretained (equivalent to assign) or weak do not perform these operations.
Weak variables can be declared using the _ week keyword. Weak variables cannot prevent the referenced objects from being destroyed.
When the referenced object is released, the weak variable is automatically set to nil.
Note that weak variables are not supported in iOS4 and Mac OS V10.6.
In this case, you can still use the unsafe_unretained and assing features for the attribute.
ARC occurs at the "bottom layer", so you don't need to worry about it.