__block作用深入研究block

本文详细探讨了__block关键字在Objective-C中的作用,解释了默认情况下Block如何复制外部变量并仅允许读取。通过例子展示了__block如何使Block内部能够修改外部变量,并分析了编译器在背后所做的工作。同时,文章还介绍了Block的存储域、copy操作以及全局块、栈块和堆块的区别。最后,提到了__block变量与__forwarding的关系,以及在ARC环境下可能产生的循环引用问题。
摘要由CSDN通过智能技术生成

block普通引用

默认情况下,在block中访问外部变量是通过复制一个变量来操作的,既可以读,但是写操作不对原变量生效,下面通过代码来举证

复制代码

NSString *a = @"testa";
    NSLog(@"block前,a在堆中的地址%p,a在栈中的地址%p",a,&a);
    void(^testBlock)(void) = ^(void){
        NSLog(@"block内,a在堆中的地址%p,a在栈中的地址%p",a,&a);
    };
    NSLog(@"block后,a在堆中的地址%p,a在栈中的地址%p",a,&a);
    testBlock();

复制代码

可以看出变量在堆中的地址其实是一直不变的,在栈中的地址,在block外是不变的,block内重新开辟了一个空间来存放。
那么来计算下两个地址变化
block前,a指向堆中的地址0x1000ec0b0,a在栈中的地址0x16fd19f58
block后,a指向堆中的地址0x1000ec0b0,a在栈中的地址0x16fd19f58
block内,a指向堆中的地址0x1000ec0b0,a在栈中的地址0x17404e0c0
十六进制的0x16fd19f58、0x17404e0c0转换为十进制数为,6170976088、6241444032。两者相差5546832956字节,再转换为MB为5289.8mb。已知IOS中一个进程的栈区内存只有1M,Mac也只有8M(等有空找官方文档求证下),又因为堆地址要小于栈地址,所以在block内调用变量,在不使用__block的情况下,是在堆中新建了一个变量地址指向原变量,block作用域结束则销毁,不影响原变量。

我们都知道:Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。在block内调用变量,在不使用__block的情况下,是在堆中新建了一个变量地址指向原变量,block作用域结束则销毁,不影响原变量。

__block关键字

由前所知,通过__block修饰,block内部不仅仅可以对外部变量进行读操作,也可以进行写操作了,那这是为什么呢?同样用代码研究两者区别

复制代码

__block NSString *a = @"testa";
    NSLog(@"block前,a指向堆中的地址%p,a在栈中的地址%p&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值