[IOS learning] 9. Implementation of Blocks

Source: Internet
Author: User

_ Block variables and objects
_ Block id obj = []; _ block id _ strong obj = []; The above two lines of code are equivalent. When the ARC is valid, the ownership modifier is bound to the id and object type variables. The default value is the _ strong modifier. Take a look at the code for clang conversion: // _ block Variable the struct _ Block_byref_obj_0 {void * _ isa; _ Block_byref_obj_0 * _ forwarding; int _ flags; int _ size; void (* _ Block_byref_id_object_copy) (void *, void *); void (* _ Block_byref_id_object_dispose) (void *); _ strong id obj ;};
Static void _ Block_byref_id_object_copy_131 (void * dst, void * src) {_ Block_object_assign (char *) dst + 40, * (void **) (char *) src + 40), 131 );}
Static void _ Block_byref_id_object_dispose_131 (void * src) {_ Block_object_dispose (* (void **) (vhar *) src + 40), 131 );}
// _ Block Variable declaration part _ Block_byref_obj_0 obj = {0, & obj, 0x2000000, sizeof (_ Block_byref_obj_0), _ Block_byref_id_object_copy_131, _ percent, [[NSObject alloc] init]};
When a Block is assigned from the stack to the heap, The _ Block_object_assign function is used to hold the object intercepted by the Block. When blocks on the stack are discarded, use the _ Block_object_dispose function to release the intercepted objects.

Only _ strong does not have _ weak? Blk_t blk; {id array = [[NSMutableArray alloc] init]; id _ weak array2 = array; blk = [^ (id obj) {[array2 addObject: obj]; NSLog (@ "array2 count = % d", [array2 count]);} copy];} blk ([[NSObject alloc] init]); blk ([[NSObject alloc] init]); blk ([NSObject alloc] init]);
The execution result is 0. this is because the variable array with the _ strong modifier is released and discarded at the end of the variable scope, and nil is assigned to the variable array2 with the _ weak modifier. The following dual modifier _ block _ weak: blk_t blk; {id array = [[NSMutableArray alloc] init]; _ block id _ weak array2 = array; blk = [^ (id obj) {[array2 addObject: obj]; NSLog (@ "array2 count = % d", [array2 count]);} copy];} blk ([[NSObject alloc] init]); blk ([[NSObject alloc] init]); blk ([[NSObject alloc] init]);
The execution result is the same as before. Because even if the _ block operator and the variable array with the _ strong modifier are appended, the array will not be released when the variable scope ends, nil is assigned to the variable array2 with the _ weak modifier.
In addition, a compilation error occurs when _ autorelease and _ block are used together.

Block loop reference
When the _ strong modifier is used in the Block, the object is held by the Block when it is copied from the stack to the heap. This will easily cause loop reference: typedef void (^ blk_t) (void); @ interface MyObject: NSObject {blk_t blk _;} @ end
@ Implementation MyObject-(id) init {self = [super init]; blk _ = ^ {NSLog (@ "self = % @", self) ;}; return self ;} -(void) dealloc {NSLog (@ "dealloc") ;}@ end int main () {id o = [[MyObject alloc] init]; in NSLog (@ "% @", o); return 0;} code, dealloc must not be called. The blk _ member variable of the Block type of the MyObject class object holds a strong reference with a value assigned to the Block. That is, the MyObject class object holds the Block. The Block syntax executed in the init instance method uses the id type variable self with the _ strong modifier. Because the Block syntax value is assigned to the member variable blk _, the Block generated on the stack is copied from the stack to the stack. And hold the self used. Self holds the Block, and the Block holds the self ~~~
To avoid circular references, you can declare variables with the _ weak modifier and assign values to self. Id _ weak tmp = self; blk _ = ^ {NSLog (@ "self = % @", tmp );};
At this time, because the Block exists, the MyObject Class Object holding the Block is assigned a value in the variable tmp self must exist, so you do not need to judge whether the value of the variable tmp is nil.
The following code will also cause loops:@ Interface MyObject: NSObject {blk_t blk _; id obj _ ;}@ end
@ Implementation MyObject-(id) init {self = [super init]; blk _ = ^ {NSLog (@ "obj _ = % @", obj _);}; return self;} @ end Block does not contain self, and it also intercepts self, causing a loop. In fact, obj _ is used in the block syntax. In fact, self: self-> obj _ has been intercepted _. As before, we can declare the Temporary Variable _ weak to avoid circular references.

We can also use the _ block Variable to avoid circular reference: typedef void (^ blk_t) (void); @ interface MyObject: NSObject {blk_t blk _;} @ end @ implementation MyObject-(id) init {self = [super init]; _ block id tmp = self; blk = ^ {NSLog (@ "self = % @", tmp); tmp = nil;}; return self;}-(void) execBlock {blk _ () ;}- (void) dealloc {NSLog (@ "dealloc ");} @ end
Int main () {id o = [[MyObject alloc] init]; [o execBlock]; return 0 ;}
Loop reference is not caused here, but if you do not call the execBlock instance method, that is, if you do not execute the Block assigned to the member variable blk _, it will reference it cyclically and cause memory leakage.
The MyObject class object holds the Block and the _ Block Variable _ block variable holds the MyObject class object.

By executing the execBlock instance method, the Block is executed, and nil is assigned to the _ block Variable tmp. Therefore, the strong reference of the _ block Variable tmp heap MyObject class object is invalid. How to avoid it? :
The MyObject class object holds the Block and holds the _ block variable.
The following describes how to use the _ block Variable to avoid circular reference and the advantages of using the _ weak modifier and the _ unsafe_unretained modifier to avoid circular reference: _ block: 1. Use the _ block Variable to control the object holding time. 2. Do not use the _ unsafe_unretained modifier in an environment where the _ weak modifier cannot be used.
Disadvantage of using the _ block Variable: Block must be executed to avoid loop reference.
However, when the Block syntax is executed and the Block path is not executed, circular reference cannot be avoided. If the Block is printed with a circular reference, use the _ Block Variable, _ weak modifier, or _ unsafe_unretained modifier Based on the block usage to avoid circular reference.


But when the ARC is invalid?In this case, we need to manually copy the Block from the stack to the heap and release the Block. Copy and release are used. When the arc is invalid, the __block specifier is used to avoid circular references in the block. This is because when the Block is assigned from the stack to the heap, if the variable used by the Block is an automatic variable of the id type or object type with the _ block specifier, it will not be retain. If the variable used by the Block is an automatic variable of the id type or object type without the _ block specifier, it will be retain. The following code will cause circular reference if it is valid or invalid in arc: typedef void (^ blk_t) (void); @ interface MyObject: NSObject {blk_t blk _;} @ end @ implementation MyObject-(id) init {self = [super init]; blk _ = ^ {NSLog (@ "self = % @", self );}; return self;}-(void) dealloc {NSLog (@ "dealloc");} @ end
Int main () {id o = [[MyObject alloc] init]; NSLog (@ "% @", o); return 0 ;}
In this case, we can avoid using the _ block Variable:
_ Block id tmp = self; blk _ = ^ {NSLog (@ "self = % @", tmp );};


---- 2014/3/22 Beijing

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.