Understanding and use of Block
Blocks is an anonymous function of Objective-C. Block is the program syntax added after iOS 4.0.
Blocks has three types: _ NSConcreteGlobalBlock, _ NSConcreteStackBlock, and _ NSConcreteMallocBlock.
1. _ NSConcreteGlobalBlock: All static blocks do not access any external variables.
2. _ NSConcreteStackBlock the block stored in the stack will be destroyed when the function returns.
3. _ NSConcreteMallocBlock: The block stored in the heap is destroyed when the reference count is 0.
Variable Replication
For variable references outside the block, the block is copied to its data structure by default for access, as shown in (picture from here ):
# Define TLog (prefix, Obj) {NSLog (@ "variable memory address: % p, variable value: % p, pointing to object Value: % @, --> % @", & Obj, prefix );}
Macro variables defined above
The following code is used:
NSString * a = @" 100 ";
TLog (@ "a --> non block", );
Void (^ block2) (void) = ^ {
TLog (@ "a --> block", );
};
A = @ "102 ";
Block2 ();
A = nil;
Block2 ();
The output is as follows:
Variable memory address: 0x7fff570d3b28, variable value: 0x0000b2c190, pointing to object Value: 100, --> a --> non block
Variable memory address: 0x7ff8bb533d00, variable value: 0x0000b2c190, pointing to object Value: 100, --> a --> block
Variable memory address: 0x7ff8bb533d00, variable value: 0x0000b2c190, pointing to object Value: 100, --> a --> block
This indicates that the external variables are copied to the block. Changes in the external variables will not cause changes in the block. The two are not the same variables. At the same time, external variables cannot be modified in the block.
_ Weak:
_ Weak NSString * B = @" 123 ";
TLog (@ "B --> non block", B );
Void (^ blocka) (void) = ^ {
TLog (@ "c --> block", B );
};
Blocka ();
B = nil;
TLog (@ "B --> 1", B );
Blocka ();
The output is as follows:
Variable memory address: 0x7fff57ddcb28, variable value: 0x0000e23190, pointing to object Value: 123, --> B --> non block
Variable memory address: 0x7fb95ae2dd10, variable value: 0x0000e23190, pointing to object Value: 123, --> c --> block
Variable memory address: 0x7fff57ddcb28, variable value: 0x0, pointing to object Value: (null), --> B --> 1
Variable memory address: 0x7fb95ae2dd10, variable value: 0x0000e23190, pointing to object Value: 123, --> c --> block
_ Weak modifier. The entire content is copied. Therefore, B = nil does not affect the block.
For external variable references modified with _ block, block copies its reference address for access, as shown in (picture from here ):
_ BlockNSString * a = @ "100 ";
TLog (@ "a --> non block", );
Void (^ block2) (void) = ^ {
TLog (@ "a --> block", );
};
A = @ "102 ";
Block2 ();
A = nil;
Block2 ();
The output is as follows:
Variable memory address: 0x7fff54e04b28, variable value: 0x10adfb1a0, pointing to object Value: 100, --> a --> non block
Variable memory address: 0x7ff52a604078, variable value: 0x10adfb220, pointing to object Value: 102, --> a --> block
Variable memory address: 0x7ff52a604078, variable value: 0x0, pointing to object Value: (null), --> a --> block
Variables modified with _ block are just pointer copies. Therefore, modifications to external variables also affect internal changes in the block. The effect is the same as that of static modification. You can modify external variables within the block.
How to Avoid block reference
NSString * a = [[NSStringalloc] initWithFormat: @ "% d", 123];
TLog (@ "a", );
_ WeakNSString * B = a; // B only performs the copy of the pointer to a, so the value change of a also affects B. At the same time, when a is released, B is also released.
TLog (@ "B --> non block", B );
Void (^ blocka) (void) = ^ {
TLog (@ "B --> block", B );
};
Blocka ();
A = nil;
Blocka ();
The output is as follows:
Variable memory address: 0x7fff53db5b28, variable value: 0x7fd4b8f1a210, pointing to object Value: 123, -->
Variable memory address: 0x7fff53db5b20, variable value: 0x7fd4b8f1a210, pointing to object Value: 123, --> B --> non block
Variable memory address: 0x7fd4b8f17b50, variable value: 0x7fd4b8f1a210, pointing to object Value: 123, --> B --> block
Variable memory address: 0x7fd4b8f17b50, variable value: 0x0, pointing to object Value: (null), --> B --> block
As shown in the preceding result
· B in the block and B outside the block are not the same variable (content copy)
· Block captures B and also provides weak references to a. When I release a outside the block, the variable cannot be read in the block.
· When a is assigned a value to nil, B in the block is also nil. That is to say, a is actually released. It can be seen that _ weak can avoid the issue of circular reference.
· _ Weak itself can avoid the problem of circular reference, but it will cause the problem that the block cannot access this object after the external object is released, we can declare a _ strong variable inside the block to point to weakObj, so that the external object can be kept inside the block and avoid the issue of circular reference.
· Use _ block
MyObject * obj = [MyObjectnew];
Obj. text = @" 123456 ";
TLog (@ "obj", obj );
_ BlockMyObject * weakObj = obj;
TLog (@ "weakObj --> non block", weakObj );
Void (^ block2) (void) = ^ {
TLog (@ "weakObj --> block", weakObj );
};
Block2 ();
Obj = nil;
· Block2 ();
· The printed result is as follows:
Variable memory address: 0x7fff5d723b28, variable value: 0x7ff999c990e0, pointing to object Value: <MyObject: 0x7ff999c990e0>, --> obj
Variable memory address: 0x7fff5d723b20, variable value: 0x7ff999c990e0, pointing to object Value: <MyObject: 0x7ff999c990e0>, --> weakObj --> non block
Variable memory address: 0x7ff999e3f098, variable value: 0x7ff999c990e0, pointing to object Value: <MyObject: 0x7ff999c990e0>, --> weakObj --> block
Variable memory address: 0x7ff999e3f098, variable value: 0x7ff999c990e0, pointing to object Value: <MyObject: 0x7ff999c990e0>, --> weakObj --> block
When the external obj points to nil, The obj should be released, but in fact blockObj still strongly references obj, which is not actually released. Therefore, the use of _ block cannot avoid the issue of circular reference.
_ Block itself cannot avoid the issue of loop reference, but we can avoid the issue of loop reference by manually assigning blockObj to nil inside the block. Another point is that the variable modified by _ block is unique inside and outside the block. Pay attention to the potential risks caused by this feature.
Reference http://blog.devtang.com/blog/2013/07/28/a-look-inside-blocks/http://honglu.me/2015/01/06/weak%E4%B8%8Eblock%E5%8C%BA%E5%88% AB/
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.