Original: Http://rypress.com/tutorials/objective-c/blocks
Blocks Block
Block is an anonymous function of OC. Block attributes enable the ability to pass a piece of code (function) before different classes, which is more intuitive than calling a method defined somewhere, and because the block is closed, external interference can be ruled out.
Creating blocks
Blocks are function-based. You can declare a block just like declaring a function, implementing a block and implementing a function is basically no different.
//main.m#import<Foundation/Foundation.h>intMainintargcConst Char*argv[]) {@autoreleasepool {//Declare The block variable Double(^distancefromrateandtime) (DoubleRateDoubleTime ); //Create and assign the blockDistancefromrateandtime = ^Double(DoubleRateDoubleTime ) { returnRate *Time ; }; //Call the block DoubleDX = Distancefromrateandtime ( *,1.5); NSLog (@"A car driving + mph would travel" @"%.2f miles in 1.5 hours.", DX); } return 0;}
^
the () symbol indicates that the Distancefromrateandtime is a block variable. Just like declaring a function, you need to indicate the return value of the block, the type of the parameter, and so on. ( ^
) Symbolic symbols can be very visually analogous to pointer symbols (for example: int *apointer), declaring block variables to be used as pointers to pointer variables.
The block definition itself is essentially the definition of a function-just no function name. ^double (double rate, double time) indicates that the current block return type is a double type, has two arguments of type double, and then defines its own processing logic in curly braces just like a normal function.
After assigning the definition to a variable, we use the fast variable as if it were a normal function.
No parameter block
If a block does not have any parameters, you can omit the parameters section in the block declaration. In addition, the return value of the block is optional at the time of definition (writable and not writable), as follows:
Double (^randompercent) (void) = ^ { return (double4294967295;}; NSLog (@ "gastank are%.1f%%full", +);
So far it seems that the block is using another difficult way to define the method. In fact it opens the door to a new way of becoming.
Closed
In blocks, there is no difference between accessing data and in methods such as: local variables, parameters, and global variables global functions. But the block is closed, so he can access non-local variables. A non-local variable is a variable that is defined outside the block, for example, the following getfullcarname can read the value of the make variable.
@" Honda " * (^getfullcarname) (NSString *) = ^ (NSString *model) { return [make] Stringbyappendingformat:@ " %@", model];}; NSLog (@ "%@", Getfullcarname (@ "Accord")) ; // Honda Accord
A non-local variable is actually a copy of the original variable when used inside the block, in other words, you cannot modify the value of the original variable in the block, they are read-only. If you forcibly modify the value of a non-local variable in a block, a compilation error will occur.
Accessing non-local variables as const
copies
In fact, in the block the fact accesses a snapshot of a non-local variable, no matter how the external non-local variable is modified, the value of the snapshot inside the block remains the block definition, and the value of the non-local variable does not change with the non-local variable, as follows:
NSString *make =@"Honda"; NSString* (^getfullcarname) (NSString *) = ^ (NSString *model) { return[Make Stringbyappendingformat:@" %@", model];}; NSLog (@"%@", Getfullcarname (@"Accord"));//Honda Accord//Try Changing the non-local variable (it won ' t change the block)make =@"Porsche"; NSLog (@"%@", Getfullcarname (@"911 Turbo"));//Honda 911 Turbo
The closure brings a good channel for exchanging data with the perimeter, without having to use parameters to pass values, and the block uses local variables as easily as this variable is defined inside the block.
mutable non-local variables
Non-local variables prohibit modification in blocks should be said to be a relatively safe practice; However, there are situations where you need to have the ability to change the value of a non-local variable, in fact there is a method, as long as the variable declaration of the time to add __block:
@" Honda ";
This declaration then tells the block that the variable is directly linked, you can modify its value.
Accessing non-local variables by reference
Just like local static
variables static local variables function in functions,__block化的变量也具有相似功能了。例如下面的例子创建一个块在每次调用i都是上次调用后的计算值。
__block int i = 0;int (^count) (void) = ^ { i + = 1; return i;}; NSLog (@ "%d", count ()); 1NSLog (@ "%d", count ()); 2NSLog (@ "%d", count ()); 3
Block as a parameter
Block variables may be useful, but in reality chunks are often used as parameters for passing. They are like function pointers but they can be directly defined in an inline way that is easier to read and understand.
For example, the car interface below declares a method for driving distances. One of its parameters takes the form of a block.
// Car.h #import <Foundation/Foundation.h>@interfacedouble odometer; -(void) Driveforduration: (double) duration withvariablespeed:(double ( ^) (double Time )) Speedfunction steps: (int) numsteps; @end
the data type of the block is double (^)(double time),指明传入的块必须返回类型为double并且具有有一个double的参数。注意块参数类型的写法和声明一个参数很像只是没有块变量名而已。
The block can be called directly using the block parameter name Speedfunction when implementing this method. The following example:
//CAR.M#import "Car.h"@implementationCar@synthesizeOdometer =_odometer;- (void) Driveforduration: (Double) Duration withvariablespeed: (Double(^) (DoubleTime )) Speedfunction Steps: (int) Numsteps {DoubleDT = Duration/numsteps; for(intI=1; i<=numsteps; i++) {_odometer+ = Speedfunction (I*DT) *DT; }}@end
As you see in the following main method, blocks can be defined directly when the method is called:
//main.m#import<Foundation/Foundation.h>#import "Car.h"intMainintargcConst Char*argv[]) {@autoreleasepool {Car*thecar =[[Car alloc] init]; //drive for awhile with constant speed of 5.0 m/s[Thecar driveforduration:10.0Withvariablespeed:^(DoubleTime ) { return 5.0; } Steps: -]; NSLog (@"The car has now driven%.2f meters", Thecar.odometer); //Start accelerating at a rate of 1.0 m/s^2[Thecar driveforduration:10.0Withvariablespeed:^(DoubleTime ) { returnTime +5.0; } Steps: -]; NSLog (@"The car has now driven%.2f meters", Thecar.odometer); } return 0;}
This is an example of a simple plot, but there are many blocks in the standard framework.NSArray可以让你通过sortedArrayUsingComparator:使用块来对元素进行排序。UIView的animateWithDuration:animations:方法
使用块定义最终的animation的状态。
Defining block types
The syntax of the block type is messy, we can use TypeDef to sign the block type, for example, the following code to create a new block type calledSpeedFunction,这样我们可以使用SpeedFunction来声明对应的块变量了。
// Car.h <foundation/foundation.h>// Define a new type for the block typedef double (^speedfunction) (double ); @interface Car:nsobject@property double odometer; -(void ) Driveforduration: (double ) duration Withvariablespeed: (speedfunction) speedfunction steps: ( int ) numsteps; @end
Summarize
Blocks provide a lot of functionality for C functions, but compared with function blocks is more intuitive and flexible.
In the next section we will go to the error handling of iOS and OS X. We will introduce two important error classes: NSException and Nserror;
9. Block