关于Block再啰嗦几句

1.一共有6种类型:

BLOCK_EXPORT void * _NSConcreteStackBlock[32];

// 只有在调用copy的情况下才会生成MallocBlock,ARC下会默认把栈上的block复制到堆上

BLOCK_EXPORT void * _NSConcreteMallocBlock[32];

BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];

//  后面三种主要是用GC

BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];

BLOCK_EXPORT void * _NSConcreteAutoBlock[32];

BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];

2.block是oc对象,含有isa的结构体

3.block只有在主动调用copy的时候, 才可能会对外部变量(主要讲oc对象)的引用计数器造成影响,会对变量进行retain操作,(__block修饰后的变量在MRC下不会对oc对象进行retain操作,需要手动管理内存),其他所有情况都不会对其引用计数器造成改变。

但是这里需要明确的是,block结构体内部其实会const一份外部变量(以参数的形式传入结构体)作为其结构体的成员变量,也就是将变量的副本存到了block结构体,所以对原对象的引用计数器没有影响。

然后在block触发函数指针调用的时候可以直接进行值传递(注意这里不是赋值的意思,是指函数方法内会生成一个局部变量,也就是外部对象,对它进行一个值传递,赋值为结构体内的变量值,也叫做截取捕捉变量),但是修改内容以及复制都不被允许,因为const化了。(全局与静态,以及__block修饰 除外)。

其实道理上也可以理解,外部的变量的作用域与生命周期问题,即使block通过指针拿到该变量的修改复制权限,其实也很危险,但变量作用域到头释放的时候,block内部的指针就是野指针。

但是%p打地址的时候你会发现对象地址还是同一个(因为本质上还是同一个对象,外部release了,Block内部也用不了)。

4.__block修饰变量相当于在block结构体内做了一次指针引用。

针对oc对象,__block其实可以看作一种提醒编译器优化的标识,加上的话该oc对象会在block结构体内会生成一个__block的对象(含有isa的结构体,含有该对象,flag = 131 = BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT,,意思是使用结构体内部的copy/dispose辅助函数手动管理,内部无需再次retain,直接指针赋值即可),并且可以使该__block对象在栈和堆上都可以得到(fowarding指针),所以也就是,即使block从栈复制到堆上,所以加上__block修饰的外部变量,当copy到堆上的时候,外部变量不会被复制(或retain),而是直接赋值指针地址,因此该变量的引用计数器保持不变。

如果不加的话(flag = BLOCK_FIELD_IS_OBJECT ),当copy到堆上时,block会调用了[obj retain]方法,引用计数器会+1, 否则复制到堆上时,会对找不到该变量(因为局部变量受作用域影响,肯定比block的生命周期短),且在复制的过程中,通过fowarding指针可以找到堆上的该变量。

非oc对象复制的话,加__block的话,flag = BLOCK_FIELD_IS_BYREF,即使复制多次也只会复制一次,后面只是将该变量的引用计数器+1(但其实对于基本数据类型的话,我们也不会去关心引用计数器)。不加__block的话,相当于block结构体对基本数据类型对象做了一次const化到了结构体内,只能使用,不能修改和赋值。

5.block作为参数,或者作为返回值时,MRC下,一定要copy到堆上,否则会超出作用域会被释放,导致野指针。这里也是日常代码时常见场合,建议最好使用ARC,编译器会默认把block复制到堆上,也就是[[block copy] autorelease]。

6.block对于以参数形式传进来的对象,不会强引用。因为传进来的参数,根本不会进入block的结构体,只是以形参的方式在block触发函数指针时出现。

7.block的循环引用问题,主要发生在当把block作用成员变量时,切记,如果block内部使用了self,或者其他成员变量(基本数据类型也不行),都会引起循环引用,__weak(ARC)和__block(MRC)都可以解决该问题。

e.g.:

__weak _-typeof(self) weakSelf = self;

^{[weakSelf someMethod];}

对block的理解不深的情况下使用,很容易造成循环引用的泛滥。其实在苹果原生的设计系统中,在View与ViewController间的通讯主要还是使用delegate。

而使用block的场合主要是类方法,比如UIView:

[UIView animateWithDuration:1.0 animations:^{

        // 动画效果

}];

8.全局变量,全部静态变量,静态变量,不需要加入__block也可以在block中被修改,全局的好理解, 作用域、生命周期都比block要大要长,所以在block内可以直接使用、修改。

静态变量(存储在.data区)也是同理,但是方案上,block在结构体内部获取了静态变量的指针,所以可以直接修改。

9.^{printf("Hello World!")} 在MRC下,clang后会发现,没有引入外部变量时,但是block结构体isa指针仍然为StackBlock,但开启ARC后,isa指针我GlobalStack指针。

推荐几篇好文&源码:(源码难看,但是还得看,否则都是道听途说)

1.http://www.jianshu.com/p/e03292674e60#

2.http://www.jianshu.com/p/51d04b7639f1

3.http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/BlocksRuntime/runtime.c

4.http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/BlocksRuntime/Block_private.h

5.http://blog.ibireme.com/2013/11/27/objc-block/

6.http://mobile.51cto.com/hot-403914.htm

7.http://mobile.51cto.com/hot-403931.htm

8.http://mobile.51cto.com/hot-403935.htm

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

推荐阅读更多精彩内容