1. block基础 block声明有点像c语言的函数指针
C代码
- int func(int);
- int (*pfunc)(int);
- int func(int p)
- {
- printf("%d", p);
- return p;
- }
其中func是函数, pfunc是函数指针
函数指针赋值 pfunc = &func;
函数指针使用 (*pfunc)(100);
block的声明 int (^bfunc)(int);
block的赋值 bfunc = ^(int p){ printf("%d", p); return p; };
block的使用 bfunc(10);
有些情况下,用户需要在多个地方用到签名相同的block,那么可以用typedef来定义block类型, 如
C代码
- typedef int (^MyBlock)(int);
- MyBlock block1 = ^(int p){
- printf("%d", p);
- return p;
- }
- MyBlock block2 = ^(int p){
- printf("%d", p * 2);
- return p * 2;
- }
2. block对外部变量的使用 对于全局变量,静态变量,类成员变量处理方式是相同的,但对于局部变量,在定义完block之后,它的值就被固定了,即使在block本身被调用之前修改了,在block内部使用的局部变量依然是block被定义时的值
以下是示例代码,其中var1是全局变量, var2是全局静态变量, var3是类的成员变量, var4是函数的局部变量。
C代码
- typedef void (^MyBlock)(int);
- ….
- var1 = 1;
- MyBlock block1 = ^(int p)
- {
- printf("\nvar1:%d", var1);
- };
- block1(0);
- var1 = 2;
- block1(0);
- var2 = 2;
- MyBlock block2 = ^(int p)
- {
- printf("\nvar2:%d", var2);
- };
- block2(0);
- var2 = 3;
- block2(0);
- var3 = 3;
- MyBlock block3 = ^(int p)
- {
- printf("\nvar3:%d", var3);
- };
- block3(0);
- var3 = 4;
- block3(0);
- var4 = 4;
- MyBlock block4 = ^(int p)
- {
- printf("\nvar4:%d", var4);
- };
- block4(0);
- var4 = 5;
- block4(0);
这段代码执行的结果是: var1:1 var1:2 var2:2 var2:3 var3:3 var3:4 var4:4 var4:4
对于全局变量、静态变量和类成员变量,block中的代码是可以修改它们的值的。 但对于局部变量,默认情况下block把它当作常量处理,如果需要修改,必须在局部变量定义的地方加上修饰符 __block
3. block和Objective-C对象变量
对于全局变量和静态变量,相比普通变量没有任何特殊的地方。 根据apple的官方文档,对于成员变量和局部变量,在block中引用会引起retainCount的变化。对成员变量的直接引用会使成员变量所在的那个对象retainCount + 1, 对局部变量的引用会使局部变量的retainCount + 1。如果对局部变量使用__block作为修饰符,就可以使局部变量被block引用时不进行retain的操作。
我自己尝试了一下,发现有一点apple的文档里没有写清楚,block对成员变量和局部变量引用时并不一定会引起retainCount的变化,以下是我的测试代码。
obj3是成员变量
C代码
- obj3 = [[TestObjectalloc] init];
- printf("\nself retain count:%d", [selfretainCount]);
- MyBlock block6 = ^(int p)
- {
- printf("\nself retain count:%d", [selfretainCount]);
- printf("\nobj retain count:%d", [obj3retainCount]);
- };
- block6(0);
- printf("\nself retain count:%d", [selfretainCount]);
输出结果: self retain count:1 self retain count:1 obj retain count:1 self retain count:1
C代码
- obj3 = [[TestObjectalloc] init];
- printf("\nself retain count:%d", [selfretainCount]);
- MyBlock block7 = ^(int p)
- {
- printf("\nself retain count:%d", [selfretainCount]);
- printf("\nobj retain count:%d", [obj3retainCount]);
- };
- MyBlock block77 = Block_copy(block7);
- block7(0); //或者 block77(0);
- printf("\nself retain count:%d", [selfretainCount]);
- Block_release(block77);
- printf("\nself retain count:%d", [selfretainCount]);
self retain count:1 self retain count:2 obj retain count:1 self retain count:2 self retain count:1
obj4是局部变量
C代码
- TestObject *obj4 = [[TestObjectalloc] initWithValue:4];
- MyBlock block8 = ^(int p)
- {
- printf("\nobj4 retain count:%d", [obj4 retainCount]);
- };
- MyBlock block88 = Block_copy(block8);
- block88(0);
- printf("\nobj4 retain count:%d", [obj4 retainCount]);
- Block_release(block88);
- printf("\nobj4 retain count:%d", [obj4 retainCount]);
obj4 retain count:2 obj4 retain count:2 obj4 retain count:1
C代码
- __block TestObject *obj5 = [[TestObjectalloc] initWithValue:5];
- MyBlock block9 = ^(int p)
- {
- printf("\nobj5 retain count:%d", [obj5 retainCount]);
- };
- MyBlock block99 = Block_copy(block9);
- block99(0);
- printf("\nobj5 retain count:%d", [obj5 retainCount]);
- Block_release(block99);
- printf("\nobj5 retain count:%d", [obj5 retainCount]);
obj5 retain count:1 obj5 retain count:1 obj5 retain count:1
结论是在一个方法内的block对对象的引用不会引起retainCount变化,但是调用Block_copy以后,retainCount会变化,但是block执行完以后引用对象的retainCount不会增加,需要调用Block_release才能释放之前Block_copy引起的retainCount增加。