Block

1、什么是局部变量,什么是全局变量

    局部变量分为自动变量(就是我们平常在函数内部定义的变量,只是默认省略了auto修饰符)和静态变量(在函数内部定义,用static修饰),局部变量之所以称为局部变量,是因为出了作用域就会销毁,但是static修饰的局部变量会一直在内存中。

2、Block的本质就是一个OC对象,他有isa指针,并且Block是封装了函数以及函数调用环境的OC对象   Block转化成的结构体中都拥有impl(里面包含了封装函数的地址)和desc(这里包括了这个Block的size 保留对象, copy方法,这个方法是用来将block从栈拷贝到堆中使用的,还有dispose方法,这个方法是block销毁的时候调用的,copy和dispose方法只有自动变量是对象类型的时候才会出现,因为只有对象类型才需要进行内存操作)


3、为了保证Block能够访问外部的变量,Block有个外部变量捕获机制,自动变量和静态变量都会被Block捕获,但是自动变量是值捕获,就是值存自动变量的值,但是静态变量是指针捕获,因为金泰变量一直在内存中,所以可以直接调用就行,所以是指针捕获。捕获局部变量的原因是自动变量出了作用域就销毁了,可是Block出了函数作用域还可以在别的函数中调用,而你封装的Block内部又访问了你已经销毁的局部变量,所以Block内部必须把局部变量通过值捕获或者指针捕获保存在Block内部

4、Block不会捕获全局变量,因为全局变量到处都能访问,跨函数也能访问,所以根本没必要再在Block内部保存一份了,直接访问就可以了


Block捕获变量图  

5、需要注意的是  如果Block内部访问了self,那么这个self也会被捕获,原因是self也是个局部变量,因为方法转换成C语言函数之后 都会变成XXX(self,_cmd),也就是说方法转换成C语言后都有固定的两个参数,一个是self,另一个是方法名称,作为参数,那么久肯定是局部变量,所以肯定会被捕获

Block的类型

1、Block都是继承自NSBlock类型的,Block分为__GlobalBlock__   、__ NSStackBlock__ 、__ NSMallocBlock__三种类型,其中__GlobalBlock__ 存放在数据区、__ NSStackBlock__存放在栈区、__ NSMallocBlock__存放在堆区

2、只要你不访问自动变量,那么Block类型就是__GlobalBlock__ 如果你访问了自动变量,在MRC上你就会是__ NSStackBlock__类型,但是在ARC上,有下面4中情况,系统会自动把BLock copy一份到堆中

    2.1、使用copy方法

    2.2、赋值给strong指针

    2.3、block作为方法名字中含有UnsignBlock的方法参数(比如枚举边里数组)

    2.4、block作为作为GCD的方法参数   

这4中情况下Block就是__ NSMallocBlock__,其余的 只要你没有访问自动变量,那就是__GlobalBlock__ ,访问了,那么你就是__ NSStackBlock__

3、如果Block访问了自动变量,但是你的这个Block只是栈上面的Block,那么这个Block内部就不会堆自动变量进行引用,强弱引用都不会,因为Block都会随时不保,引用自动变量也没有多大意义。如果Block被拷贝到了堆上面,那么就会调用Block内部的Copy方法,copy法法内部就会调用_Block_object_assign函数,会根据自动变量是weak类型,还是strong类型还是unsafe_unretained类型,来对该自动变量进行强弱引用。当Block销毁的时候,会调用Block内部的dispose方法,根据_Block_object_dispose函数来对已经引用的自动变量进行释放

Block修改自动变量

    1.block访问了自动变量,自动变量只是值传递,如果你要在block内部就改变不了这个自动变量的值

    2、但是如果你的自动变量是指针传递,那么因为你的内部引用了该指针,所以你就能改变这个指针所指对象的值(static修饰的局部变量,全局变量)

    3、如果不能修改自动变量,你需要用__block来修饰该自动变量,__block内部是将该自动变量包装成了一个新的对象,这个新的对象中有个指向自己的指针,如果你要修改该自动变量,他就会通过forwarding指针找到被包装的这个对象,然后修改里面的值


Block修改被__block修饰的对象

4、为什么非要弄一个forwarding指针来指向自己呢,为什么不通过Block内部指向结构体的指针找到你要修改的自动变量来进行修改呢

    答:因为自动变量生成的时候都是在栈区的,通过Block的自动捕获机制,还有用__block修饰之后,把你的这个自动变量包装成了一个结构体,Block内部的指向结构体的指针指向了这个结构体,Block一旦被copy到了堆区,那么这个结构体也被复制到了堆区,会调用block内部的copy函数,copy函数内部会调用_Block_object_assign函数,_Block_object_assign函数会对__block变量形成强引用(根据变量修饰符来决定),但是我们修改变量后,我们都希望只对堆取得自动变量进行修改,因为修改栈区的没意义,但是吐过你访问的是战区的自动变量,然后修改了,那就达不到效果了,这个时候,就需要指向自己的指针了,如果你访问的是站上的自动变量,站上的自动变量的forwarding指针指向的是堆中的__block包装的结构体,然后再堆中的结构体找到forwarding找到堆中结构体里面的自动变量进行修改,如果你修改的是堆中的自动变量,那就直接找到堆中的结构体进行修改,所以forwarding的作用就是无论你修改的是占中的自动变量还是堆中的,都能保证修改了堆中的自动变量


forwarding指针

5、Block在栈上时,并不会对__block变量进行强引用,当block被copy到堆时会调用block内部的copy函数,copy函数内部会调用_Block_object_assign函数,_Block_object_assign函数会对__block变量形成强引用(非对象类型,对象类型还要根据修饰符决定是否强引用,如果是MRC  那么一定是弱引用)

6、当block从堆中移除时,会调用block内部的dispose函数,dispose函数内部会调用_Block_object_dispose函数,_Block_object_dispose函数会自动释放引用的__block变量(release)


ARC循环引用问题图解


MRC下循环应用问题
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容