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的内存管理:
直接上题目:
- Example A
- void exampleA() {
- char a = 'A';
- ^{
- printf("%c\n", a);
- }();
- }
- A:always work
- B:only work with ARC
- C:always workout ARC
- A:never work
- Example B
- void exampleB_addBlockToArray(NSMutableArray *array) {
- char b = 'B';
- [array addObject:^{
- printf("%c\n", b);
- }];
- }
- void exampleB() {
- NSMutableArray *array = [NSMutableArray array];
- exampleB_addBlockToArray(array);
- void (^block)() = [array objectAtIndex:0];
- block();
- }
- A:always work
- B:only work with ARC
- C:always workout ARC
- A:never work
- Example C
- void exampleC_addBlockToArray(NSMutableArray *array) {
- [array addObject:^{
- printf("C\n");
- }];
- }
- void exampleC() {
- NSMutableArray *array = [NSMutableArray array];
- exampleC_addBlockToArray(array);
- void (^block)() = [array objectAtIndex:0];
- block();
- }
- A:always work
- B:only work with ARC
- C:always workout ARC
- A:never work
- Example D
- typedef void (^dBlock)();
- dBlock exampleD_getBlock() {
- char d = 'D';
- return ^{
- printf("%c\n", d);
- };
- }
- void exampleD() {
- exampleD_getBlock()();
- }
- A:always work
- B:only work with ARC
- C:always workout ARC
- A:never work
- Example E
- typedef void (^eBlock)();
- eBlock exampleE_getBlock() {
- char e = 'E';
- void (^block)() = ^{
- printf("%c\n", e);
- };
- return block;
- }
- void exampleE() {
- eBlock block = exampleE_getBlock();
- block();
- }
- A:always work
- B:only work with ARC
- C:always workout ARC
- A:never work
- Example F
- int multiplier = 7 ;
- void (^myBlock)( void ) = ^()
- {
- multiplier=7;
- };
- printf ( "%d" , myBlock( ));
- 问:上面代码有问题吗?有则指出。
Example A
在arc和mrc下都可以完美运行。
Example B
在arc下可以运行, 这个block使用了外部变量,他的类型NSStackBlock,位于栈内存,方法结束后本应该无效,然而在arc,block会自动转成mallocblock。所以在方法结束后不会有问题。
mrc: 在这个下面,block被加入到array中,方法结束,block无效,数组中的block成了野指针,在取出时就会报错,所在在mrc下需要这么写 :
- void (^block)() = ^{
- printf("%c\n", b);
- };
- [ array addObject:[[block copy ] autorelease]];
Example C:
在arc和mrc下都可以运行
Example D:
在arc下可以完美运行。
在mrc下,连编译都通过不了,因为编译器不允许返回一个localstack ,位于本地栈中的block
Exampe E:
这一题,在arc和mrc下都可以运行,但是与我的想法是不符合的,同理于Example D,应该也会报错
- char e = 'E';
- void (^block)() = ^{
- printf("%c\n", e);
- };
- 2. NSLog(@"%@",^{
- printf("%c\n", e);
- });
- NSLog(@"%@",block);
- return block;
- }
- void exampleE() {
- eBlock block = exampleE_getBlock();
- NSLog(@"%@",block);
- 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不能直接打印。