Block
In Objective-c, NSArray is one of the most commonly used containers. In many cases, we need to sort the data in the array. Therefore, code similar to the following will often encounter:
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) { if ([obj1 integerValue] > [obj2 integerValue]) { return (NSComparisonResult)NSOrderedDescending; } if ([obj1 integerValue] < [obj2 integerValue]) { return (NSComparisonResult)NSOrderedAscending; } return (NSComparisonResult)NSOrderedSame;}];
Friends who are new to objc may not understand this code.
SortedArrayUsingComparator: ^ (id obj1, id obj2) {// Code omitted}];
The parameter type starting with ^ is NSComparetor. The prototype is as follows:
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
In fact, the Comparetor function is similar to the function pointer in C language, and Lambda expressions in C ++ 11, Java 8, and C.
Function pointer in C Language
First, let's review the simplest function pointer in C language.
returntype (*name) (arg);
Defines a function pointer variable. Or define a function pointer type in the form of typedef. The sample code is as follows:
// C language function pointer declaration int (* addInC) (int, int); // declare this type of function pointer as an AddOperation type typedef int (* AddOperation) (int, int); // common C language function int doAdd (int a, int B) {return a + B;} // int main (int argc, const char * argv []) {@ autoreleasepool {// The addInC pointer variable points to the doAdd function addInC = doAdd; NSLog (@ "addInC: % I. ", addInC (5, 6); // function pointer call // declare an aop function pointer variable, also pointing to doAdd AddOperation aop = doAdd; NSLog (@" AddOperation: % I. ", aop (100, 23);} return 0 ;}
Output:
addInC : 11.AddOperation : 123.
The first is to define a function pointer, addInC, and then point addInC to the doAdd function in the main function. Calling addInC (5, 6) is equivalent to calling doAdd (5, 6 ). Similarly, this is also the principle of AddOperation. Lambda expressions in Java 8
Blocks in Objc
Now we return to the Block in Objc, which is the Block used in the NSArray sorting above. Let's take a look at the official definition:
Blocks are a language-level feature added to C, Objective-C and C++, which allow you to create distinct segments of code that can be passed around to methods or functions as if they were values. Blocks are Objective-C objects, which means they can be added to collections like NSArray or NSDictionary. They also have the ability to capture values from the enclosing scope, making them similar to closures or lambdas in other programming languages.
The last sentence clearly states that the block is similar to lambda and closure in other languages.
Let's take a look at the block declaration format:
returnType (^name) (arguments)
ReturnType indicates the type of the returned value, name indicates the variable name, argments indicates the parameter list, and void or () can be written if no parameter exists ().
Let's take a look at the block Definition Format:
^ [returnType] (arguments) { statements };
ReturnType is optional, arguments is the parameter list, and statements is the code that implements the function. The following is an example:
// Return value, but optional when defining block functions. int (^ addUseBlock) (int, int) = ^/* int */(int a, int B) {return a + B ;};
We declare the addUseBlock variable and then point it to a block with two int parameters. Int type returned during definition can be omitted. The call code is as follows:
// Use the Block Function NSLog (@ "add use Blockm, Result => % I.", addUseBlock (3, 4 ));
3 + 4 results are returned.
Define a block as a Type
We can use typedef to define a block as a type like function pointers in C, so that the block can be passed as a function. The following defines a Comparetor type with an int return value and two int row parameters. The example is as follows:
// Define a Compare type typedef int (^ Comparetor) (int arg1, int arg2 );
This looks like NSComparator in NSArray, but it only returns different types.
At this time, it is much easier to use blocks as parameters, as shown in the following example:
// Block as the parameter int helpCompare (Comparetor cmp) {return cmp (3, 4);} // return a Block object Comparetor getComparetor () {return ^ (int, int B) {return a> B? -1: 1 ;};}// int main (int argc, const char * argv []) {@ autoreleasepool {// use the Comparetor type to define Block Comparetor cmp = ^ (int a, int B) {if (a = B) {return 0;} return a> B? 1:-1 ;}; NSLog (@ "use Comparetor, Result ==> % I. ", cmp (3, 4); // use the cmp of the Comparetor type as the NSLog parameter (@" use Comparetor, Result => % I. ", helpCompare (cmp); // use an anonymous function of the Comparetor type as a parameter. The 123 NSLog (@" use Comparetor, Result => % I. ", helpCompare (^ (int a, int B) {return 123 ;})); // return a Block through the function, and pass it as a parameter to helpCompare NSLog (@ "use Comparetor, Result => % I. ", helpCompare (getComparetor ();} return 0 ;}
The output is as follows:
use Comparetor, Result ==> -1.use Comparetor, Result ==> -1.use Comparetor, Result ==> 123.use Comparetor, Result ==> 1.
The block uses the context variable block code to use the variables in its range, but the block code cannot modify or reference the value of the variable, such as the variable of the function where the block is located and the member variable of the class. To modify the value in the block code, use _ block to define the variable. Example:
Int main (int argc, const char * argv []) {@ autoreleasepool {// use the context variable int valueInMain = 222; void (^ printValue) () = ^ () {NSLog (@ "variable using the function context (cannot be modified): % I. ", valueInMain) ;}; printValue (); _ block int anInteger = 42; void (^ testBlock) (void) =^{ anInteger = 100; NSLog (@ "variables declared using _ block (can be modified): % I", anInteger) ;}; testBlock () ;}return 0 ;}
The output is as follows:
Variables using the function context (which cannot be modified): 222. variables declared using _ block (which can be modified): 100