1.声明和使用代码块
一般用^操作符声明一个块变量,并作为块的开始符。而块的本身用{}包括起来,就像下面那样。
int multiplier = 7;
|
int (^myBlock)(int) = ^(int num) {
|
return num * multiplier;
|
};
|
int(^myblocks)(int)=(^int num){return num * multiplier};
其实意思就是前半句声明了一个名字为myBlock的代码块,有一个int类型的参数,并返回一个int类型的值;后面的半句就是一个块的定义,然后赋值给myBlock。
如果我们像上面那样,声明一个块像一个变量一样,我们就可以像使用函数一样使用它,如下:
int multiplier = 7;
|
int (^myBlock)(int) = ^(int num) {
|
return num * multiplier;
|
};
|
|
printf("%d", myBlock(3));
|
// prints "21"
|
2.直接使用block
在大多数情况下,我们不需要去声明一个块变量,我们直接写一个简单的代码块作为参数传递就行。下面的代码函数qsort_b的第三个参数就是一个代码块。
char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
|
|
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
|
char *left = *(char **)l;
|
char *right = *(char **)r;
|
return strncmp(left, right, 1);
|
});
|
|
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }
|
一些cocoa frameworks的方法采用一个block作为一个参数,典型的是对一个集合对象进行操作,或者是在一个操作完成之后使用回调。下面的例子是NSArray类的方法
sortedArrayUsingComparator:怎样使用一个block。此方法使用一个block作为一个参数。
NSArray *stringsArray = [NSArray arrayWithObjects:
|
@"string 1",
|
@"String 21",
|
@"string 12",
|
@"String 11",
|
@"String 02", nil];
|
|
static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch |
|
NSWidthInsensitiveSearch | NSForcedOrderingSearch;
|
NSLocale *currentLocale = [NSLocale currentLocale];
|
|
NSComparator finderSortBlock = ^(id string1, id string2) {
|
|
NSRange string1Range = NSMakeRange(0, [string1 length]);
|
return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
|
};
|
|
NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
|
NSLog(@"finderSortArray: %@", finderSortArray);
|
|
|
block的一个强大的功能是可以修改同一作用雨的变量,我们只需要在变量的前面加上一个_block标识符。下面的例子和上面的相同,只是添加功能用于记录相同元素的个数。
NSArray *stringsArray = [NSArray arrayWithObjects:
|
@"string 1",
|
@"String 21", // <-
|
@"string 12",
|
@"String 11",
|
@"Strîng 21", // <-
|
@"Striñg 21", // <-
|
@"String 02", nil];
|
|
NSLocale *currentLocale = [NSLocale currentLocale];
|
__block NSUInteger orderedSameCount = 0;
|
|
NSArray *diacriticInsensitiveSortArray = [stringsArray sortedArrayUsingComparator:^(id string1, id string2) {
|
|
NSRange string1Range = NSMakeRange(0, [string1 length]);
|
NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale];
|
|
if (comparisonResult == NSOrderedSame) {
|
orderedSameCount++;
|
}
|
return comparisonResult;
|
}];
|
|
NSLog(@"diacriticInsensitiveSortArray: %@", diacriticInsensitiveSortArray);
|
NSLog(@"orderedSameCount: %d", orderedSameCount);
|
|
|
3.block变量的声明
block的声明和函数指针差不多,只是把*改为了^
void (^blockReturningVoidWithVoidArgument)(void);
|
int (^blockReturningIntWithIntAndCharArguments)(int, char);
|
void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);
|
也可以使用typedef去声明block,方便以后使用,如下:
typedef float (^MyBlockType)(float, float);
|
|
MyBlockType myFirstBlock = // ... ;
|
MyBlockType mySecondBlock = // ... ;
|
4.变量的作用域对于其在块中的影响:
_block int x = 123; // x lives in block storage
|
|
void (^printXAndY)(int) = ^(int y) {
|
|
x = x + y;
|
printf("%d %d\n", x, y);
|
};
|
printXAndY(456); // prints: 579 456
|
// x is now 579
|
extern NSInteger CounterGlobal;
|
static NSInteger CounterStatic;
|
|
{
|
NSInteger localCounter = 42;
|
__block char localCharacter;
|
|
void (^aBlock)(void) = ^(void) {
|
++CounterGlobal;
|
++CounterStatic;
|
CounterGlobal = localCounter; // localCounter fixed at block creation
|
localCharacter = ‘a‘; // sets localCharacter in enclosing scope
|
};
|
|
++localCounter; // unseen by the block
|
localCharacter = ‘b‘;
|
|
aBlock(); // execute the block
|
// localCharacter now ‘a‘
|
}
|
5.使用blocks
(1)调用一个声明好的block
int (^oneFrom)(int) = ^(int anInt) {
|
return anInt - 1;
|
};
|
|
printf("1 from 10 is %d", oneFrom(10));
|
// Prints "1 from 10 is 9"
|
|
float (^distanceTraveled) (float, float, float) =
|
^(float startingSpeed, float acceleration, float time) {
|
|
float distance = (startingSpeed * time) + (0.5 * acceleration * time * time);
|
return distance;
|
};
|
|
float howFar = distanceTraveled(0.0, 9.8, 1.0);
|
// howFar = 4.9
|