Block circular reference and retain cycle in iOS (classic)

Source: Internet
Author: User

The generation of retain cycle

Speaking of retain cycle, the first thing to mention is the OBJECTIVE-C memory management mechanism.

As a superset of the C language, Objective-c continues to manage memory manually in the C language, but differs from the extremely inhumane memory management of C + +, and OBJECTIVE-C proposes mechanisms to reduce the difficulty of memory management. For example: Memory count.

In Objective-c, the classes that inherit from NSObject provide two methods, retain and release. When we invoke the retain of an object, the memory count of this object is added to 1, whereas when we call release, the object's memory count is reduced by 1, and the object is actually freed only when the object memory count is 0 o'clock. The Delloc method of the object is called to do some work before the memory is recycled.

The advantage of the memory counting mechanism is that we can explicitly assign a right to use. For example, when an object A is going to use another object B, a will retain B once to indicate that a uses B, and when B is finished, a will call the release method of B to discard the use. In this way, an object can be used by multiple other objects. And as an object to use it, you don't have to worry about the use of objects that are used outside of yourself (memory side). In general, for class member variables, retain and release occur respectively when assigning and releasing themselves, which is the classic notation in the OBJ-C program:

In the header file:

@property (nonatomic,retain) NSObject *obj;

In the. m file:

- (void)dealloc{    [obj release];    [super dealloc];}

OK, this is an easy way to manage memory, but there is still this problem, which is retain cycle.

Retain cycle, translated into Chinese is probably called the Reserve ring bar. Now that the parent object is holding child objects and the child objects are released with the parent object, what if two objects are parent to each other?

For example A and B two objects, a holds b,b also holds a, according to the above rules, a only B released after the possibility of release, the same B only a release can be released, when both sides are waiting for the other release, retain cycle formed, the result is that two objects will never be released, Final memory leak.

Retain cycle makes you have to pay attention to some problems when you program. For example, if you try to keep a child object referring to the parent object, use a weak reference, which is assign, such as

@property (nonatomic,assign) NSObject *parent;

Either set a variable in the retain cycle to nil, and break the ring off in a timely manner. If you pay attention, this is not a particularly big problem.

Well, it's really not a problem to be aware of, but when iOS 4 comes in, Block appears, making you more cautious.

Block and memory management

Block is a flexible code that you can use as a variable, assign it, and even declare it in the function body, and more flexibly you can refer to the external environment inside. The last one makes the block more considered, since block can reference the external environment, how to ensure that the block is called when the environment variables are not released? (The time of block invocation may be arbitrary)

The answer is that the variables referenced by the block are automatically retain once, at least to ensure that our call is valid.

What can you think of here? Yes, or retain cycle. Because the retain in block is implicit, it is very easy to retain cycle problems.

Because the block itself can also be considered as an object, there is also a life cycle, it can be held, so when this happens, we should pay attention to, for example:

DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{    //...complete actions    [manager otherAction];    [manager release];};

Retain cycle is so formed that even if the call to Release,manager is not released, because the manager and block hold each other. To relieve retain cycle, we can write:

DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{    //...complete actions    [manager otherAction];    manager.complete = nil;    [manager release];};

The manager's complete is set to nil, so that retain cycle is destroyed as long as you do not need to callback the block again.

It would have been written here, but the new century has always had a new challenge, which is that Apple has launched a new technology ARC.

ARC and Retain cycle

ARC (Auto Reference counting), translated as automatic reference counting, is the technology that Apple has introduced to further simplify memory management. Although it is for automatic memory management, it is not really automatic management. This is because arc is a compile-time technique that automatically recognizes your code and transforms it into a retain/release form, and at this level, arc simply simplifies the writing of the Code and provides partial performance optimizations, Rather than a language like Java, the garbage collection can be completely left behind (basically). The details of arc can be seen at the following URL:

http://developer.apple.com/library/ios/#releasenotes/objectivec/rn-transitioningtoarc/introduction/introduction.html

Below we mainly talk about the arc under the retain cycle problem.

In arc, a variable can be decorated with three keywords:

__strong: The object assigned to the variable is automatically retain once, and if it is referenced in the block, the block will retain it once. __unsafe_unretained: assignment to this variable will not be retain, that is, the existence of a variable that he modifies does not guarantee the reliability of the holding object, it may have been released, and an unsafe pointer has been left. Will not be retain by block. __week: Similar to __unsafe_unretained, but if the object being held is freed, the variable is automatically set to nil, which is more secure, But only in IOS5.0 above the system support, also will not be block retain.

In addition, we can use the __block keyword to modify a variable, indicating that the variable can be modified in the block (value modification, rather than modifying one of the object's properties, it can be understood to modify the pointer pointing). will be automatically retain.

Unlike other variables, variables that are __block modified are stored in the block as the address of the variable. (The other is the value of the variable)

First of all, the above code you can now write:

DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{    //...complete actions    [manager otherAction];    manager.complete = nil;};

No problem, just remove the banned release from Arc.

Of course, we can also write this.

__block DoSomethingManager *manager = [[DoSomethingManager alloc] init];manager.complete = ^{    //...complete actions    [manager otherAction];    manager = nil;};

If you don't use Arc,manager, you won't be retain in the block, but using arc is a bit more complicated. The block will retain the manager variable, but since the __block variable holds the more underlying variable address, the block is not responsible for the original object when the variable is pointed to another object, and the result is that the object was previously removed, retain Cycle was destroyed.

or write this:

__block DoSomethingManager *manager = [[DoSomethingManager alloc] init];DoSomethingManager __week *weekmanager = manager;manager.complete = ^{    //...complete actions    [weekmanager otherAction];};

The above __week can also be replaced with __unsafe_unretained , but __week is more secure, although it does not support IOS5.0 systems below.

Variables modified by __week or __unsafe_unretained are not retain by block, so retain cycle is not formed, but be careful, Ensure that your object is not released before complete, or you will get results that you do not intend.

Original address: http://www.cnblogs.com/tangbinblog/archive/2012/12/31/2840690.html

Block circular reference and retain cycle in iOS (classic)

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.