objective-c+中代码块(blocks)

原文地址:http://blog.sina.com.cn/s/blog_67419c420100vl8b.html

<wbr>在ios4之后,引入了代码块的特性,在gcd中会经常的用到,所以决定好好的看看代码块文档,把这块总结一下。从头开始讲解代码块。 </wbr>


1.声明和使用代码块
一般用^操作符声明一个块变量,并作为块的开始符。而块的本身用{}包括起来,就像下面那样。
 int multiplier = 7;
 int (^myBlock)(int) = ^(int num) {
 return num * multiplier;
 };

下面的图是详细的讲解:
objective-c+中代码块(blocks)
<wbr><wbr><wbr>其实意思就是前半句声明了一个名字为myBlock的代码块,有一个int类型的参数,并返回一个int类型的值;后面的半句就是一个块的定义,然后赋值给myBlock。</wbr></wbr></wbr>
<wbr><wbr><wbr>如果我们像上面那样,声明一个块像一个变量一样,我们就可以像使用函数一样使用它,如下:</wbr></wbr></wbr>
 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" }

<wbr><wbr>一些cocoa frameworks的方法采用一个block作为一个参数,典型的是对一个集合对象进行操作,或者是在一个操作完成之后使用回调。下面的例子是NSArray类的方法<span style="font-family:Courier,Consolas,monospace; font-size:13px; color:#666666; line-height:normal"><a href="http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/sortedArrayUsingComparator:" target="_self">sortedArrayUsingComparat<wbr>or:</wbr></a></span>怎样使用一个block。此方法使用一个block作为一个参数。</wbr></wbr>
 NSArray *stringsArray = [NSArray arrayWithObjects:
 @"string 1",
 @"String 21",
 @"string 12",
 @"String 11",
 @"String 02", nil];
 
 static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch |
 NSWidthInsensitiveSearch<wbr> | NSForcedOrderingSearch;</wbr>
 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 = [stringsArraysortedArrayUsingComparat<wbr>or:finderSortBlock];</wbr>
 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 *diacriticInsensitiveSort<wbr>Array = [stringsArray sortedArrayUsingComparat<wbr>or:^(id string1, id string2) {</wbr></wbr>
 
 NSRange string1Range = NSMakeRange(0, [string1 length]);
 NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSe<wbr>arch range:string1Range locale:currentLocale];</wbr>
 
 if (comparisonResult == NSOrderedSame) {
 orderedSameCount++;
 }
 return comparisonResult;
 }];
 
 NSLog(@"diacriticInsensitiveSort<wbr>Array: %@", diacriticInsensitiveSort<wbr>Array);</wbr></wbr>
 NSLog(@"orderedSameCount: %d", orderedSameCount);
 
 

3.block变量的声明
block的声明和函数指针差不多,只是把*改为了^
 void (^blockReturningVoidWithVo<wbr>idArgument)(void);</wbr>
 int (^blockReturningIntWithInt<wbr>AndCharArguments)(int, char);</wbr>
 void (^arrayOfTenBlocksReturnin<wbr>gVoidWithIntArgument[10])(int);</wbr>
也可以使用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

你可能感兴趣的:(Objective-C)