Blocks is an extension of the C language: An anonymous function with an automatic variable (local variable). With blocks, anonymous functions can be used in the source code, that is, functions without names. In our work, name occupies a large part, function name, variable name, property name, class name, frame name, etc. must have. Being able to write a function without a name is quite attractive to programmers.
Blocks syntax
The complete form of blocks is compared with the general C-language function, with two different points.
- No name of the function
- With
^
Blocks BN Paradigm
Block_literal_expression ::= ^ block_decl compound_statement_bodyblock_decl ::=block_decl ::= parameter_listblock_decl ::= type_expression
Translation into plain English is
^返回值类型 (参数列表)表达式
1. 返回值类型 return value types in the same OC/C syntax
2. The parameter 参数列表 list in the same C syntax, the parameters in OC are passed through, and the syntax here is more like the list of parameters contained in the C language ().
3. 表达式 expressions allowed in the same OC/C syntax
Such as
^int (int count){ return count++; }^NSString * (NSNumber *num){ return [NSString stringWithFormat:@"%@",num]; };
People may wonder why it's Blocks not always the case, because blocks can omit several items
Blocks omitted sentence omitting return value type
Such as:
^return value type (参数列表)表达式
You can 返回值类型 omit the
The above code example can be written as
^(int count){ return count++; }^(NSNumber *num){ return [NSString stringWithFormat:@"%@",num]; };
So, it seems to be more familiar.
When you omit a return value type, if there is a return statement in the expression that uses the type of the return value, if there is no return statement in the expression, use the void type, as shown in the following code example.
The complete definition sentence is given below (using the omitted return value type sentence)
^(int count){return count+1 ;}; ^(NSNumber *num){ return [NSString stringWithFormat:@"%@",num]; }; ^(NSNumber *count){ NSLog(@"无返回类型Block count = %@", count); }; ^(void){ NSLog(@"无返回类型也无参数 Block"); };
Omit argument list
If parameters are not used, the argument list can also be omitted
^return value type (parameter list)表达式
If there is no return value type above, the block with no parameters is also simplified to
^{ NSLog(@"无返回类型也无参数 Block");};
Block type variable
The block described above is the same as the C/OC definition in syntax format, except for the absence of a name and a carry ^ .
In block syntax, the block syntax can be assigned to variables declared as block types. That is, once the block syntax is used in the source code, it is equivalent to generating a value that can be assigned to the block type variable. The value generated by the block syntax in Blocks is also known as "block".
An example of declaring a Block type variable is as follows:
int (^counts)(int);
The Block type variable has no difference from other C/OC variables and can be used for the following purposes
- Automatic variables
- function parameters
- static variables
- Static global variables
- Global variables
Let's try to assign a block to the block type variable using the block syntax
Int (^counts) (int) = ^ (int count) {return count+1;}; nsstring * (^STR) (nsnumber *num) = ^ nsstring * (nsnumber *num) { return [nsstring stringwithformat:@ "%@", Num];}; void (^blank) (nsnumber *count) = ^ ( nsnumber *count) {nslog (@ "no return type block count =%@", count);}; void (^blank) (void) = ^ (void) {nslog (@" no return type and no parameter Block ");};
Use the block type variable in the function argument to pass the block to the function, and Block the variable as the function's formal parameter
func(int (^counts)(int)){}
When the Block is used as a type variable parameter, the description method and its complexity, such as the above parameter, can be used to simplify the description, as is the case with the function pointer type typedef .
int (^count) (int);
Override the method above
func(count num){}
This is the C wording of the language, replaced by the OC wording, so that everyone more clear, in the definition of the same use
/** * 原来的写法 */-(void)funcWithCount:(int (^)(int))count{}/** * 使用typedef之后的写法 */-(void)funcWithCount:(count )count{}
Simple usage
Once you have defined block blocks of code, you can use a whole block of code as a variable, either as a local variable or as a global variable, which I think is the most convenient place to block.
Suppose you want to generate two arrays, one with 5 random numbers, one with 10 random numbers, and a method that generates a random number as a closure, which can be accessed directly later, as
NSNumber * (^randarray) (void) = ^{int rand = arc4random ()% 100; nsnumber *number = [nsnumber Numberwithint:rand]; return number;}; Nsmutablearray *array1 = [[Nsmutablearray alloc] init]; Nsmutablearray *array2 = [[Nsmutablearray alloc] init]; For (nsinteger index = 0; index<; index++) {[Array1 addobject:randarray ()];} For (nsinteger index = 0; index<5; index++) {[Array2 addobject:randarray ()];}
Callback
Here is an example of a tableViewCell button event callback, which is a headache for many people, the block can be easily implemented, and the level is very clear.
The custom cell is named blockCell , a control is placed on the cell, and we want the switch to be in the state of the switch switch when clicked viewController and get the Click event.
In the blockCell.h definition of aBlock
typedef void(^switchAction)(blockCell *);@property (nonatomic,copy)switchAction action;
Called in a switch's click-time EventswitchAction
blockCell.m
- (IBAction)switchToggle:(id)sender { self.action(self);}
The viewController table is initialized with this custom cell in
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *cellID = @"blockCell"; blockCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; cell.action = ^(blockCell *cell){ // 既可取到行,也可取到switch状态 NSLog(@"行数:%ld, switch state: %u", (long)indexPath.row, cell.switchBtn.on); }; return cell; }
Pass Value
Now a lot of popular third-party libraries have changed the callback to block, before using the delegate particularly handy have wood, are packaged well directly call to get the results I want, OK, all changed to block, do not know how to pick up the return value of block, can only be rewritten again and generally.
In fact, to encapsulate is very easy, the third-party library to return the block, a block to catch and then return to call the page on it, this would like to introduce
AFNetworingAfter this, but I looked down, github on their homepage, the readme written super clear details, want to know the children's shoes please carefully look at theirreadMe
How to add
GitHub Address: https://github.com/AFNetworking/AFNetworking
The class library can be copied to the project directory to add, recommended for cocoapods installation, easy to update, and do not have to manually import the framework, one-click Settings
Packaging
Objective: To call the corresponding method to get the network return value directly after passing the parameter
Create a new class WebRequest , here to write an example, you reference
#import <Foundation/Foundation.h>#import "AFNetworking.h"@interface WebRequest : NSObject-(void)requestNameWithID:(NSString *)ID WithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject, NSDictionary *myData))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;@end
@implementationwebrequest-(void) Requestnamewithid: (NSString *) ID withsuccess: (void (^) (Afhttprequestoperation *operation,ID Responseobject,Nsdictionary *mydata)) succes failure: (void (^) (Afhttprequestoperation *operation,Nserror *error)) Failure {nsurl *url = [nsurl urlwithstring: @ "with ID splicing interface address"]; nsurlrequest *request = [nsurlrequest RequestWithURL:url]; Afhttprequestoperation *operation = [[Afhttprequestoperation alloc] initwithrequest:request]; [Operation setcompletionblockwithsuccess:^ (Afhttprequestoperation *operation, id Responseobject) {nsdictionary *dic = Responseobject[@ " Somekey "]; Success (operation, Responseobject, DIC); //here to pass the network return value to our own defined block of three return values, DIC can be customized, also can not add, so you can return to the object you have already handled here, without having to call once, processing} failure:^ (afhttprequestoperation *operation, nserror *error) {failure (operation,error) ; //and block in method definition}];} @end
Call
*request = [[WebRequest alloc] init];[request requestNameWithID:@"123" WithSuccess:^(AFHTTPRequestOperation *operation, id responseObject, NSDictionary *myData) { // 在网络成功时在这里就可以得到返回值了,operation,responseObject,myData} failure:^(AFHTTPRequestOperation *operation, NSError *error) { // 网络失败回调}];
Sample Project Download
Teach you to love blocks (closures)