Objective-C Memory Management

Source: Internet
Author: User

Objective-C Memory Management

In IOS development, swift has been used before, so the memory management mechanism of Objective-C has been in a confusing state for a long time. today, I finally saw a thorough blog Objective-C memory management tutorial and Principle Analysis. Thank you for the author.
This article is just a personal learning abstract. For more details, refer to the original article.

Basic Memory Allocation

The OC object is generated in the heap and needs a pointer to it.

ClassA *obj1 = [[ClassA alloc] init];

It will not be destroyed automatically after use. You need to execute dealloc to destroy it. Otherwise, memory leakage may occur.

[obj1 dealloc];

The following code is used:

ClassA * obj1 = [[ClassA alloc] init]; ClassA * obj2 = obj1; [obj1 hello]; [obj1 dealloc]; // obj1 and obj2 are pointers pointing to the same object. [obj1 dealloc] has destroyed this object. therefore, the following code cannot be executed, and obj2 is an invalid pointer. [obj2 hello]; [obj2 dealloc];
Reference count

To avoid the above Invalid Pointer, OC uses the reference counting method. the values of reference count plus 1 include alloc, retain, strong, and 1 minus release. when the reference count of an object is 0, dealloc is automatically called.

ClassA * obj1 = [[ClassA alloc] init]; // The count is 1 [obj1 release]; // The count is 0, automatic deallocClassA * obj1 = [[ClassA alloc] init]; // The count is 1 ClassA * obj2 = obj1; // The count is 1, pointer assignment does not add reference count [obj1 hello]; [obj1 release]; // The count is 0, and automatic dealloc // the following code is not executed because the object has been dealloc, obj2 is still an invalid pointer. [obj2 hello]; [obj2 release];

So how can we solve the obj2 Invalid Pointer problem? Add 1 to the reference count using retain.

ClassA * obj1 = [[ClassA alloc] init]; // The count is 1 ClassA * obj2 = obj1; // The count is 1 [obj2 retain]; // The count is 2 [obj1 hello]; [obj1 release]; // The count is 1 [obj2 hello]; [obj2 release]; // The count is 0, and the automatic dealloc

Therefore, when the reference count of an object is 0, dealloc is automatically called to destroy the object. When the pointer value is assigned, retain count does not automatically increase. Manual retain is required.
In addition, after release is an object, the pointer should be cleared immediately (a null pointer of release is valid). For example:

ClassA *obj1 = [[ClassA alloc] init];[obj1 release];obj1 = nil;
Autorelease

The automatic release pool is actually a NSAID oreleasepool, which can automatically release objects.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

An NSMutableArray exists in the nutoreleasepool to save all objects declared as autorelease.

ClassA * obj1 = [[ClassA alloc] init] autorelease]; // The reference count is 1, and the object is added to the autorelease pool.

Let's take a look at the example of Apple:
Do not use autorelease first,

- (NSString *)fullName {    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName];    return string;}

Then, the string cannot find the appropriate time to release, so Memory leakage may occur.
After using autorelease,

- (NSString *)fullName {    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName] autorelease];    return string;}

Although string will not be released immediately, autorelease will release it at its release time.
Or you can use the following method:

- (NSString *)fullName {    NSString *string = [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];    return string;}

During the destruction of the NSAID utoreleasepool itself, it traverses and tries to release all the autorelease objects. if the reference count of this object is 1, the reference count is reduced by 1 and the object is destroyed. If the reference count of this object is greater than 1, the reference count after autorelease is greater than 0, the object is not destroyed and Memory leakage occurs.
For example, in the main. m file of the iOS project

int main(int argc, char * argv[]) {    @autoreleasepool {        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));   }}

Actually, you can use the NSAID utoreleasepool on your own,

NSAID utoreleasepool * pool = [[NSAID utoreleasepool alloc] init]; for (int I = 0; I <100; I ++) {for (int j = 0; j <10000; j ++) {// generate the autorelease object [NSString stringWithFromat: @ "1234567890"] ;}} [pool release]; return 0;

It can be seen that all autorelease objects can be destroyed only when the release is executed in the NSAID utoreleasepool. Obviously, the memory cannot be well utilized. Therefore, you can use the embedded NSAID utoreleasepool. The code optimization is as follows:

| For (int j = 0; j <10000; j ++) {// generate the autorelease object [NSString stringWithFromat: @ "1234567890"];} [loopPool release];} [pool release]; return 0;

In this way, the memory can be released in a timely manner.
Because the oc object is a dynamic memory and has no stack concept, you cannot return an object to the stack as C does. You can only use the autorelease object.
Therefore, the key to the NSAID utoreleasepool is that the autorelease objects placed in the pool will be automatically destroyed during the pool release (in most cases, the autorelease objects with a normal reference count of 1 ). therefore, the object itself does not need to call the release method. at the same time, the release time of the NSAID utoreleasepool is very important.
Do not misuse autorelease. If the object's lifecycle is clear, it will be immediately release after use. Too many waiting for autorelease objects to waste memory.

Keywords in property

All the keywords in property are used to set the operation features of getter/setter.

Assign

Assign is equivalent to a pointer value, and does not operate on the reference count. If the original object does not need to be used, set it to nil.
That is, the value is assigned directly when the setter method is called, and the retain operation is not performed. The reference count is not changed.

Copy

Copy content. Copy an object to a new object (new memory address). The reference count of the new object is 1, and the reference count of the original object remains unchanged. The NSCopying protocol is followed.
MutableCopy: copying an object. The reference count of the new object is 1.
That is to say, all the objects obtained by copy are independent objects.

Retain

Retain is actually a pointer copy (with the same address), which increases the reference count of the object, while the basic data type or CoreFoundation object does not have reference count.
Add the object to the array. The reference count increases the number of object references + 1.
That is, when the setter method is called, the old value of release is first used to reference and count the new value. + 1. The memory addresses of the two are the same.

Strong

Strong is a strong reference, and the reference count of the object is + 1. If both string1 and string2 point to a string, string1 = nil, while string2 remains unchanged.
The strong variable executes the ARC count and will not be automatically released. Its death directly determines the death of the object to which it points.
To ensure that the instances in use are not destroyed, ARC tracks and computes the attributes, constants, and variables that each instance is being referenced. Even if the number of instances referenced is 1, ARC will not destroy this instance.
To make it possible, no matter you assign an instance a value to an attribute, constant or variable, attribute, constant or variable, you will create a strong reference for this instance. It is called a strong reference because it will hold the instance firmly. As long as the strong reference is still in place, the instance cannot be destroyed.

Weak

To prevent cyclic strong references, weak references and no primary references can be used. These two types allow one instance of the cyclic reference to reference another instance without retaining strong reference, so that the instance can reference each other without generating a circular strong reference.
Weak reference: used for instances that change to nil in the life cycle.
No primary reference: it is used for instances that will no longer change to nil after initialization and assignment.
Weak is a weak reference, and the object count remains unchanged. For example, if both string1 and string2 point to a string, then string1 = nil, then string2 will also change to nil.
Because it does not have a retain memory address, if the address object to which it points is released, the pointer will point to nil.
When the ARC is idle, the pointer is automatically set to NULL when the object is released. it does not determine the survival of an object. Even if an object is held with countless weak references, as long as there is no strong reference pointing to it, the object will be cleared.
If two objects are member variables of the other, they must not be retain at the same time. Otherwise, the dealloc function will form a deadlock and both objects cannot be released. weak can be used to prevent wild pointers and deadlocks and avoid circular references.

_ Weak

_ Weak declares a weak reference that can be automatically nil-based.
Note: The use of self in the Code may lead to retain cycle, so the _ weak method is generally used. Please refer to the example of the city list below.
In CityListVC, the city value is passed to MainVC through the block.
In CityListVC. h: Define block object

Typedef void (^ SelectedCity) (NSString *); @ property (copy, nonatomic) SelectedCity selectCity; CityListVC. m: if (_ selectCity) {_ selectCity (cell. textLabel. text); // data transmission between views through blocks .}

In MainVC. h:

typedef void(^SelectedCity)(NSString *);@property(copy,nonatomic) SelectedCity selectCity;

In MainVC. m:

Self. vTracks. selectedCity = @ "city"; _ weak MainViewController * weakVC = self; _ selectCity = ^ (NSString * city) {weakVC. cityLabel. text = ([city isw.tostring: @ "nationwide"])? @ "City": city; weakVC. vTracks. selectedCity = ([city isEqualToString: @ "city"] | [city isEqualToString: @ "nationwide"])? Nil: city; [weakVC. vTracks invokeRefresh] ;};

In the block, the _ weak method is used to declare a weakVC. The weak reference method can avoid loop reference.

Static

Static can be regarded as a class variable and has nothing to do with the object instance. the static variables of the instantiated objects do not affect each other, but the changes will affect the class itself. if a new object is added, the new object will have the latest static variables.

Const

Const, a constant cannot be modified. It will be released after it is out of scope. That is, const is a constant for the lifetime of the object and variable for the entire class.

Extern

Extern: global variable.

Read and Write Permissions

Readwrite, readonly: controls the access permission of member variables.

Atomic operation

Nonatomic: Non-atomic access, no synchronization, and multi-thread concurrent access.
Atomic thread protection. mutex lock.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.