block和GCD是ios高级程序员面试必问的问题,本篇先介绍下block
第一部分:概述
实体形式如下:
^(传入参数列){行为主体}
lock实体开头是“^”,接着是由小括号所包起来的参数列(比如
int a, int b, int c),行为主体由大括号包起来,专有名字叫做block literal。行为主体可以用return回传值,类型会被compiler自动辨别。如果没有参数列要写成:
^(void)。
第二部分:具体用法
一:block的初级用法
/*test 1 使用^运算子来宣告一个block变数*/ int multiplier = 7; int (^myblock)(int) = ^(int num){ return num*multiplier; }; printf("%d\n",myblock(5)); /*test 2 在需要使用block的地方直接用内嵌的方式将block的内容写出来*/ char * myCharacters[3] = {"TomJohn","George","Charles Condomine"}; qsort_b(myCharacters, 3, sizeof(char*), ^(const void*l,const void*r)//排序函数,个人感觉sort快速排序很好用 { char*left = *(char**)l; char*right= *(char**)r; return strncmp(left, right, 1); } ); printf("%s\n",myCharacters[0]); /*test 3 在block内修改变量*/ __block int multiplier2 = 7; int(^myblock2)(int) = ^(int num){ if (num>5) { multiplier2 = 0; }else{ multiplier2 = 3; } return multiplier2; }; NSLog(@"%d,%d\n",myblock2(8),myblock2(3));
二:定义一个block
可以参考,对照block的实体形式
/*回传void,参数也是void的block*/ void(^blockReturningVoidWithVoidArgument)(void); /*回传整数,两个参数分别是整数和字元形态的block*/ int (^blockReturningIntWithIntAndCharArguments)(int,char); /*回传void,含有10个block的阵列,每个block都有一个形态为整数的参数*/ void(^arrayofTenBlockReturningVoidWinIntArgument[10])(int);
/*test 1 区域变数的使用方式*/ // 加上__block 修饰词变量才能在block中修改操作 int x = 123; void (^printXAndY)(int) = ^(int y){ printf("%d,%d\n",x,y); }; printXAndY(20); // 加上__block 修饰词变量才能在block中操作 /*test 2 各个类型的变数和block之间的互动*/ NSInteger localCounter = 42; __block char localCharacter; void (^aBlock)(void) = ^(void) { // ++CounterGlobal;//可以存取 ++CounterStatic;//可以存取 // CounterGlobal = localCounter; localCharacter = 'a'; }; ++localCounter; localCharacter = 'b'; aBlock(); printf("test2:%ld,%ld,%c\n",localCounter,CounterStatic,localCharacter);四:使用block
/*test 1 当block宣告成一个变数时,我们可以像使用一般函数的方式来使用它*/ int (^twoFrom)(int) = ^(int anInt){ return anInt-1; }; printf("1 from 10 is %d\n",twoFrom(10)); float (^distanceTraveled)(float,float,float) = ^(float startingSpeed,float acceleration,float time){ float distance = (startingSpeed*time)+(0.5*acceleration*time*time); return distance; }; printf("howFar %f\n",distanceTraveled(0.0,9.8,1.0)); /*test 2 一般情况下若是将block当做是参数传入函数,我们通常会使用内嵌的方式来使用block*/ char*myCharacter_s[3] = {"TomJohn","George","Charles Condomine"}; qsort_b(myCharacter_s, 3, sizeof(char*), ^(const void*l,const void*r){ char*left = *(char**)l; char*right = *(char**)r; return strncmp(left, right, 1); }); /*test 3 在上边的例子中,block本身就是函数参数的一部分,在下一个例子中dispatch——apply函数中使用block,dispatch_apply的定义如下*/ // void dispatch_apply(size_t iterations,dispatch_queue_t queue,void(^block)(size_t)); size_t count = 12; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply(count, queue, ^(size_t i){//类似于for循环 printf("%zu\n",i*2); }); /*test 4 SDK中提供了很多使用block的方法,我们可以像传递一般参数的方式来传递block,下面这个范例示范如何在一个阵列的前五笔资料中取出我们想要的资料的索引值*/ //所有的资料 NSArray*array = [NSArray arrayWithObjects:@"A",@"B",@"C",@"A",@"B",@"Z",@"G",@"are",@"Q", nil]; //我们只要这个集合内的资料 NSSet*filterSet = [NSSet setWithObjects:@"A",@"B",@"Z",@"Q", nil]; BOOL(^test)(id obj,NSUInteger idx,BOOL*stop); test = ^(id obj,NSUInteger idx,BOOL *stop){ if (idx<5) { if ([filterSet containsObject:obj]) { return YES; } } return NO; }; NSIndexSet*indexes = [array indexesOfObjectsPassingTest:test]; NSLog(@"indexes:%@",indexes);
原文地址:http://blog.csdn.net/lv_ruanruan/article/details/38872265