block详解

Objective-C 中 Block 有三种类型:

NSStackBlock    存储于栈区
NSGlobalBlock   存储于程序数据区
NSMallocBlock   存储于堆区



block 内部没有引用外部变量的 Block 类型都是 NSGlobalBlock 类型,存储于全局数据区,由系统管理其内存,retain、copy、release操作都无效。

block 变量在赋值的时候系统自动将其拷贝到堆区了,造成我们看到变量 block 是 NSMallocBlock 类型。

Block属性的特性限定符一般都是 copy,因为其setter方法中会拷贝一份新的副本到堆区



系统在编译block时,发现有个num变量,外部没有用__block修饰,系统会在堆区中创建一个同名同类型的变量,在真正执行代码的时候,如果没有对num进行修改的操作,那么就会直接调用堆区中的num的值,这个值是在编译的时候已经赋给堆区变量的,打印(简单地说这个时候block内部与外部没有任何的关系),当block执行完毕后,调用的num还是之前的栈区中创建的num

程序在编译block代码块的时候,发现num是被__block修饰的,就不会上来就在堆区中创建num变量,而是在执行到这里的时候才去按照外部的同名变量去在堆区中创建num,与此同时,会修改外部变量的地址,这个地址是堆区中num的地址,所以在最后打印num的地址,是指向堆区的,因而获取的值也是堆区中num的值

当block作为函数参数时为_NSConcreteStackBlock类型。在函数中,在block执行完毕前,函数是不会退出的。

block作为函数的返回值时为_NSMallocBlock类型


不应该使用__weak来修饰对象,让dispatch_after对self进行持有,保证block执行时self还未被释放。

 在block执行开始时self对象还未被释放,而执行过程中,self被释放了,此时访问self时,就会发生错误。

 对于这种场景,应该在block中对 对象使用__strong修饰,使得在block期间对 对象持有,block执行结束后,解除其持有。

 
 
block结构体定义如下:

  struct Block_layout{

        void *isa;//指向表明该block类型的类  是_NSConcreteStackBlock

         int flags;//按bit位标示一些的block的附加信息,比如判断block类型、判断block引用计数、判断block是否需要执行辅助函数等。

         int reserved;//保留变量

         void (* invoke)(void *,...);//函数指针,执行具体的block实现的函数调用地址。

         struct Block_descriptor  *descriptor;//block的附加信息,比如保留变量数,block的大小,进行copy活dispose得辅助函数指针。

         /*Imported variables*/ //因为block有比暴行,所以可以访问block外部的局部变量。这些variables就是复制到结构体中的外部局部变量或变量的地址。 

  };

转载于:https://www.cnblogs.com/diyigechengxu/p/9187891.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值