iOS中__block底层原理是怎么样的
2019-05-08 本文已影响0人
guoguojianshu
我们都知道block是会对申明它的范围内,所有变量都可以为其捕获的。这也就是说,那个范围内的全部变量,在块里依然可用的。但是不能对捕获的变量进行修改,除非加上
__block
的标志才可以进行修改,这个底层是怎么回事呢?
先对基本数据类型进行查看
- 1没有使用__block时候的情况
int num = 10;
NSLog(@"初始化时候的指针 %p",&num);
void (^ myBlock)(void) = ^{
NSLog(@"block中的指针%p",&num);
};
myBlock();
NSLog(@"被block捕获后的指针%p",&num);
打印结果为
2019-05-08 11:02:58.925066+0800 block[58634:10234102] 初始化时候的指针 0x7ffeef5cb9ec
2019-05-08 11:02:58.925222+0800 block[58634:10234102] block中的指针0x600000396180
2019-05-08 11:02:58.925309+0800 block[58634:10234102] 被block捕获后的指针0x7ffeef5cb9ec
1.如何确定指针是在栈中,还是在堆中呢,看指针的大小,因为栈中的指针是很大的,是从高地址开始分配的,堆中的指针是从低地址开始分配的;
或者是把这些16进制的指针转为10进制,然后用大指针数减去小指针数,获得字节差,再除以两次1024,可以得到多少M的空间,因为堆地址要小于栈地址,又因为iOS中一个进程的栈区内存只有1M,Mac也只有8M,显然num已经是在堆区了。
注意:但是最后的指针又回到栈了。
- 2 使用__block表示后
__block int num = 10;
NSLog(@"初始化时候的指针 %p",&num);
void (^ myBlock)(void) = ^{
NSLog(@"block中的指针%p",&num);
};
myBlock();
NSLog(@"被block捕获后的指针%p",&num);
打印结果
2019-05-08 11:34:28.594960+0800 block[59001:10269363] 初始化时候的指针 0x7ffee29699e8
2019-05-08 11:34:28.595104+0800 block[59001:10269363] block中的指针0x6000001f4d38
2019-05-08 11:34:28.595193+0800 block[59001:10269363] 被block捕获后的指针0x6000001f4d38
有__block标识的,最后的指针也会在堆中,
总结:加入了__block的表示后,栈中的指针地址永久的被copy到堆中了,不加入__block时候,只是在block内部时候会被暂时的从栈中被copy到堆中,等block结束后又回到栈中了,因为block对象布局中有copy方法,所以可以进行copy操作
对对象的情况
NSMutableString * mString = [NSMutableString stringWithString:@"xiaoli"];
NSLog(@"初始化时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
void(^myBlock)(void) = ^{
mString.string = @"xiaowang";
NSLog(@"在block中的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
};
myBlock();
NSLog(@"在block执行完之后的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
打印结果
2019-05-08 12:02:30.881439+0800 block[59318:10294124] 初始化时候 mString指向堆中的地址0x6000004fb180
mString在栈中的指针地址0x7ffee95b09e8 mString = xiaoli
2019-05-08 12:02:30.881615+0800 block[59318:10294124] 在block中的时候 mString指向堆中的地址0x6000004fb180
mString在栈中的指针地址0x6000004fbfb0 mString = xiaowang
2019-05-08 12:02:30.881698+0800 block[59318:10294124] 在block执行完之后的时候 mString指向堆中的地址0x6000004fb180
mString在栈中的指针地址0x7ffee95b09e8 mString = xiaowang
加入__block表示后
__block NSMutableString * mString = [NSMutableString stringWithString:@"xiaoli"];
NSLog(@"初始化时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
void(^myBlock)(void) = ^{
mString.string = @"xiaowang";
NSLog(@"在block中的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
};
myBlock();
NSLog(@"在block执行完之后的时候 mString指向堆中的地址%p\n mString在栈中的指针地址%p mString = %@",mString,&mString,mString);
打印结果
2019-05-08 12:06:47.865743+0800 block[59378:10299298] 初始化时候 mString指向堆中的地址0x600002507a20
mString在栈中的指针地址0x7ffeeae199e8 mString = xiaoli
2019-05-08 12:06:47.865886+0800 block[59378:10299298] 在block中的时候 mString指向堆中的地址0x600002507a20
mString在栈中的指针地址0x6000025079b8 mString = xiaowang
2019-05-08 12:06:47.866087+0800 block[59378:10299298] 在block执行完之后的时候 mString指向堆中的地址0x600002507a20
mString在栈中的指针地址0x6000025079b8 mString = xiaowang