首页 > 代码库 > objective c 代码块blocks完整总结二

objective c 代码块blocks完整总结二

1. block基础 block声明有点像c语言的函数指针

C代码 
  1. int func(int);  
  2.   
  3. int (*pfunc)(int);  
  4.   
  5. int func(int p)  
  6. {  
  7.   printf("%d", p);  
  8.   return p;  
  9. }  

 

其中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代码 
  1. typedef int (^MyBlock)(int);  
  2. MyBlock block1 = ^(int p){  
  3.   printf("%d", p);  
  4.   return p;  
  5. }  
  6.   
  7. MyBlock block2 = ^(int p){  
  8.   printf("%d", p * 2);  
  9.   return p * 2;  
  10. }  

 

2. block对外部变量的使用 对于全局变量,静态变量,类成员变量处理方式是相同的,但对于局部变量,在定义完block之后,它的值就被固定了,即使在block本身被调用之前修改了,在block内部使用的局部变量依然是block被定义时的值
以下是示例代码,其中var1是全局变量, var2是全局静态变量, var3是类的成员变量, var4是函数的局部变量。

C代码 
  1. typedef void (^MyBlock)(int);  
  2. ….  
  3.   
  4.   
  5. var1 = 1;  
  6. MyBlock block1 = ^(int p)  
  7. {  
  8.     printf("\nvar1:%d", var1);  
  9. };  
  10.   
  11. block1(0);  
  12. var1 = 2;  
  13. block1(0);  
  14.      
  15. var2 = 2;  
  16. MyBlock block2 = ^(int p)  
  17. {  
  18.     printf("\nvar2:%d", var2);  
  19. };  
  20.   
  21.   
  22. block2(0);  
  23. var2 = 3;  
  24. block2(0);  
  25.      
  26. var3 = 3;  
  27. MyBlock block3 = ^(int p)  
  28. {  
  29.     printf("\nvar3:%d", var3);  
  30. };  
  31.      
  32. block3(0);  
  33. var3 = 4;  
  34. block3(0);  
  35.      
  36. var4 = 4;  
  37. MyBlock block4 = ^(int p)  
  38. {  
  39.     printf("\nvar4:%d", var4);  
  40. };  
  41.   
  42.   
  43. block4(0);  
  44. var4 = 5;  
  45. 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代码 
  1. obj3 = [[TestObjectalloc] init];  
  2. printf("\nself retain count:%d", [selfretainCount]);  
  3. MyBlock block6 = ^(int p)  
  4. {  
  5.     printf("\nself retain count:%d", [selfretainCount]);  
  6.     printf("\nobj retain count:%d", [obj3retainCount]);  
  7. };  
  8. block6(0);  
  9. printf("\nself retain count:%d", [selfretainCount]);  

 

输出结果: self retain count:1 self retain count:1 obj retain count:1 self retain count:1

C代码 
  1. obj3 = [[TestObjectalloc] init];  
  2. printf("\nself retain count:%d", [selfretainCount]);  
  3. MyBlock block7 = ^(int p)  
  4. {  
  5.     printf("\nself retain count:%d", [selfretainCount]);  
  6.     printf("\nobj retain count:%d", [obj3retainCount]);  
  7. };  
  8. MyBlock block77 = Block_copy(block7);  
  9. block7(0); //或者 block77(0);  
  10. printf("\nself retain count:%d", [selfretainCount]);  
  11. Block_release(block77);  
  12. 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代码 
  1. TestObject *obj4 = [[TestObjectalloc] initWithValue:4];  
  2. MyBlock block8 = ^(int p)  
  3. {  
  4.     printf("\nobj4 retain count:%d", [obj4 retainCount]);  
  5. };  
  6. MyBlock block88 = Block_copy(block8);  
  7. block88(0);  
  8. printf("\nobj4 retain count:%d", [obj4 retainCount]);  
  9. Block_release(block88);  
  10. printf("\nobj4 retain count:%d", [obj4 retainCount]);  

 

obj4 retain count:2 obj4 retain count:2 obj4 retain count:1

C代码 
  1. __block TestObject *obj5 = [[TestObjectalloc] initWithValue:5];  
  2. MyBlock block9 = ^(int p)  
  3. {  
  4.     printf("\nobj5 retain count:%d", [obj5 retainCount]);  
  5. };  
  6. MyBlock block99 = Block_copy(block9);  
  7. block99(0);  
  8. printf("\nobj5 retain count:%d", [obj5 retainCount]);  
  9. Block_release(block99);  
  10. 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增加。

objective c 代码块blocks完整总结二