关于block(四)----block类型

block本身是像对象一样可以retain,和release,但是栈block和全局block这些操作都无效,只有堆block操作有效,虽然retainCount始终是1但是内存管理器中仍然增减计数。使用retain也可以,但是block的retain行为默认是用copy的行为实现的,
因为block引用外部变量时默认是声明为栈Block的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

一、globalBlock无论什么操作都是globalBlock

二、block在什么情况下会copy到mallocBlock?

1.在block中如果有引用外部变量(默认声明为栈Block),且,block被赋值给__strong对象 或者 [block copy]
2.栈Block作为方法、函数的返回值,其实这是一种copy操作
3.GCD或UsingBlock:方法引用block,其实这也是线程或者其他对象强引用了Block
只有stackBlock才有可能变为mallocBlock。

代码1

void(^myBlock)(void) = ^() {
    printf("ss");
};
myBlock();

这里的block没有引用外部变量,存储在代码中,为全局类型,NSGlobalBlock

代码2

char *str = "qqq";  
void(^myBlock)(void) = ^{
    NSLog(@"%s",str);
};
myBlock();

表面看这里的block引用外部变量,存储在栈中,离开作用域就会释放;
但是实际上这里的myBlock是存放在堆中NSMallocBlock,原因是因为这里在将block赋值给myBlock2时,在ARC下系统将block copy到了堆里

代码3

char *str = "aass";
//__NSStackBlock__
NSLog(@"%@",^{printf("%s",str);});
//__NSStackBlock__,直接在栈中被调用
^{printf("%s",str);}();

这里输出的block就是存放在栈里面了,这里没有赋值操作

代码4

char *str = "qqq";
//__NSStackBlock__,这里虽然进行了赋值操作,但是赋值的对象是__weak
__weak Blk blockWeak = ^() {
    printf("%s",str);
};
blockWeak();
//__NSMallocBlock__,这里给__strong block对象赋值
__strong Blk blockStrong = ^() {
    printf("%s",str);
};
blockStrong();

代码5

__block int h = 9;
//__NSStackBlock__,直接在栈中被调用,因为没有copy也没有给__strong对象赋值
^{h = 11;printf("%d",h);}();
//__NSStackBlock__,直接在栈中被调用,因为没有copy也没有给__strong对象赋值
NSLog(@"%@",^{h = 12;printf("%d",h);});

你可能感兴趣的:(关于block(四)----block类型)