Block面试题解析

13 篇文章 0 订阅
Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。他在是一个仿对象,也可以说是一种特殊的对象,他有三种类型:

1.NSGlobalBlock:类似函数,位于text段

2.NSStackBlock:位于栈内存,函数返回后Block将无效;

3.NSMallocBlock:位于堆内存。


第一种类型:说简单一点,就是不使用外部的变量的block块就是NSGlobalBlock,可以把他看待成一个静态block。

第二种类型:和第一种相反,block块如果使用了外部变量,那么他就会变成NSStackBlock,他在内存中处于堆内存。 在声明他的函数执行结束后,block将无效。

第三种类型:这种那些第block位于堆内存中,这种类型的block是有NSStackBlock进行copy后产生的,在arc下面就会自动copy变成mallocblock,而且stack block如果被用作返回值类型,会自动copy成mallocblock,如果是使用weak类型的指针那么不会自动copy,请注意,那么这种类型第block就和对象的地址一样了,他的retain,copy,release都和对象的作用差不多,只不过要注意的是copy的话,不会产生新的对象,只会retain block一次 retainCount+1 ; 

下图直观的展示了三种类型的block的内存管理:




直接上题目:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example A  
  2.   
  3. void exampleA() {  
  4.     char a = 'A';  
  5.     ^{  
  6.         printf("%c\n", a);  
  7.     }();  
  8. }  
  9. A:always work  
  10. B:only work with ARC  
  11. C:always workout ARC  
  12. A:never work  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example B  
  2. void exampleB_addBlockToArray(NSMutableArray *array) {  
  3.     char b = 'B';  
  4.     [array addObject:^{  
  5.         printf("%c\n", b);  
  6.     }];  
  7. }  
  8. void exampleB() {  
  9.     NSMutableArray *array = [NSMutableArray array];  
  10.     exampleB_addBlockToArray(array);  
  11.     void (^block)() = [array objectAtIndex:0];  
  12.     block();  
  13. }  
  14. A:always work  
  15. B:only work with ARC  
  16. C:always workout ARC  
  17. A:never work  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example C  
  2.   
  3. void exampleC_addBlockToArray(NSMutableArray *array) {  
  4.     [array addObject:^{  
  5.         printf("C\n");  
  6.     }];  
  7. }  
  8. void exampleC() {  
  9.     NSMutableArray *array = [NSMutableArray array];  
  10.     exampleC_addBlockToArray(array);  
  11.     void (^block)() = [array objectAtIndex:0];  
  12.     block();  
  13. }  
  14. A:always work  
  15. B:only work with ARC  
  16. C:always workout ARC  
  17. A:never work  
  18.    

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example D  
  2. typedef void (^dBlock)();  
  3.   
  4. dBlock exampleD_getBlock() {  
  5.     char d = 'D';  
  6.     return ^{  
  7.         printf("%c\n", d);  
  8.     };  
  9. }  
  10.   
  11. void exampleD() {  
  12.     exampleD_getBlock()();  
  13. }  
  14. A:always work  
  15. B:only work with ARC  
  16. C:always workout ARC  
  17. A:never work  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example E  
  2. typedef void (^eBlock)();  
  3.   
  4. eBlock exampleE_getBlock() {  
  5.     char e = 'E';  
  6.     void (^block)() = ^{  
  7.         printf("%c\n", e);  
  8.     };  
  9.     return block;  
  10. }  
  11.   
  12. void exampleE() {  
  13.     eBlock block = exampleE_getBlock();  
  14.     block();  
  15. }  
  16.   
  17. A:always work  
  18. B:only work with ARC  
  19. C:always workout ARC  
  20. A:never work  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Example F  
  2.   
  3.     int multiplier = 7 ;  
  4.      void (^myBlock)( void ) = ^()  
  5.     {  
  6.             multiplier=7;  
  7.         };  
  8. printf ( "%d" , myBlock( ));  
  9. 问:上面代码有问题吗?有则指出。  


Example A

在arc和mrc下都可以完美运行。


Example B

在arc下可以运行, 这个block使用了外部变量,他的类型NSStackBlock,位于栈内存,方法结束后本应该无效,然而在arc,block会自动转成mallocblock。所以在方法结束后不会有问题。

mrc:  在这个下面,block被加入到array中,方法结束,block无效,数组中的block成了野指针,在取出时就会报错,所在在mrc下需要这么写  :  

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void (^block)() = ^{  
  2.     printf("%c\n", b);  
  3. };  
  4.  [ array addObject:[[block copy ] autorelease]];  

Example C:

在arc和mrc下都可以运行


Example D:

在arc下可以完美运行。

在mrc下,连编译都通过不了,因为编译器不允许返回一个localstack ,位于本地栈中的block


Exampe E:

这一题,在arc和mrc下都可以运行,但是与我的想法是不符合的,同理于Example D,应该也会报错

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.   char e = 'E';  
  2.    void (^block)() = ^{  
  3.         printf("%c\n", e);  
  4.     };  
  5.       
  6.  2.   NSLog(@"%@",^{  
  7.         printf("%c\n", e);  
  8.     });  
  9.       
  10.     NSLog(@"%@",block);  
  11.       
  12.     return block;  
  13.  }  
  14.   
  15. void exampleE() {  
  16.     eBlock block = exampleE_getBlock();  
  17.     NSLog(@"%@",block);  
  18.      block();  
打印如下:

2014-08-02 12:41:19.356 Block_test[1054:303] <__NSStackBlock__: 0x7fff5fbff7c0>

2014-08-02 12:41:19.358 Block_test[1054:303] <__NSStackBlock__: 0x7fff5fbff7e8>

2014-08-02 12:41:19.359 Block_test[1054:303] <__NSStackBlock__: 0x7fff5fbff7e8>


这里如果换成return 2  这个block的话 就会报错,  这里我也不太懂。。。我想区别就在于这两种声明方法的不同,百度了也找了一些 , 没有看到很好的解释,如果有大神在看,希望能给出答案.



Example F:不管在arc 或者 mdc下都会报错.

错误1: block引用局部变量时,只能读不能写。否则会报错,对于static变量和全局变量都可以随意使用.

错误2:   argument type ‘void’ is incomplete 会报这个错,意思是返回参赛是void,是不完整的。所以没有返回值的block不能直接打印。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值