I. Overview
Block is a C-level syntax and runtime feature. Block is similar to the C function, but the block is more flexible than the C function, which is reflected in the stack memory, heap memory reference, and we can even pass a block as a parameter to other functions or block.
second, warm up
Let's look at a relatively simple block example:
int multiplier = 7;
Int (^myblock) (int) = ^ (int num) {
return num * multiplier;
};
In this example, Myblock is a block variable that takes a parameter of type int and returns a value of type int. Does it look like a C function?
Come on, let's have a typedef.
typedef void (^boolblock) (bool);//A block that accepts only one BOOL parameter and no return value
typedef int (^intblock) (void);//A block that returns an int without parameters
typedef boolblock (^hugeblock) (intblock);//See, this hugeblock parameter and return value are block
Third, more detailed examples
Note: The typedef above are also valid ~
Take the initiative to call:
-(void) SomeMethod
{
Boolblock Ablock = ^ (BOOL bValue) {
NSLog (@ "Bool block!");
};
Ablock ();
}
Returned as a parameter:
typedef void (^boolblock) (BOOL);
-(Boolblock) foo ()
{
Boolblock Ablock = ^ (BOOL bValue) {
NSLog (@ "Bool block!");
};
return [[ablock copy] autorelease];//Be sure to copy it to the heap, more detailed principles will be explained in subsequent chapters
}
A member of the class:
@interface Obj1:nsobject
@property (nonatomic, copy) Boolblock block;//reasons why, boys.
@end
OBJ1 *obj1 = ...
Obj1.block = ^ (BOOL bValue) {
NSLog (@ "Bool block!");
};
Parameters for other functions:
-(void) foo (Boolblock block)
{
if (block) {
Block ();
}
}
Even other block parameters:
Boolblock bblock = ^ (BOOL bV) {if (BV) {/*do some thing*/}};
Hugeblock Hblock = ^ (boolblock bb) {BB ();};
Hbolck (bblock);
Ah, global Variables! :
static int (^maxintblock) (int, int) = ^ (int a, int b) {return a>b?a:b;};
int main ()
{
printf ("%d\n", Maxintblock (2,10));
return 0;
}
Well, you know how the block might be used.
four, special markings, __block
If you want to modify the stack variables declared outside of block within a block, be sure to add __block tags to the variable:
int main ()
{
__block int i = 1024;
Boolblock bblock = ^ (BOOL bV) {
if (BV) {
i++;//If there is no __block tag, it cannot be compiled.
}
};
}
Precautions:
Blocks can be used entirely as a substitute for delegatge, and are simple to use and do not need to write too many @protocol to define interfaces. However, the use of the following points is noted.
(1) block is not an object, so the retain is not valid, to preserve the block life cycle, it is best to copy to achieve, of course, after the copy, remember release. If you do not want to manage manually, you can manage it by [[[[Testblock] copy] autorelease].
(2) We know that the object of the general block application, Retaincount will automatically add one, in order to break this retain circle, you can add __block before the object, so block blocks will not maintain this object. There are two kinds of situations
(1) A reference to a temporary variable such as: a =[[[a alloc] init] withblock:^{
[A action];
[A release];
}]; In fact, this can lead to memory leaks, in order to break this circle, only need to add __block in front of a. In my test code, the program crashes directly due to the absence of a plus __block.
That
__block a =[[[A alloc] init] withblock:^{
[A action];
[A release];
}]; So the Dealloc method of a will call
(2) References to instance variables, such as
A =[[[a alloc] init] withblock:^{
[Self action];
}]; So even if the release method of the self itself class is called, it will not be freed as long as the block is not executed. To break this can be done by the following
__block typeof (self) bself = self; The expression reference, specifically reference typeof usage, indicates that bself is the self type.
A =[[[a alloc] init] withblock:^{
[Bself Action];
}]; so that the blocks and self are independent of each other.
Block Application and Precautions