Block

闭包:一个函数或指向函数的指针,再加上执行外部的上下文变量(自由变量)

Block是OC对于闭包概念的实现,是一种特殊的数据类型,可代替delegate,广泛应用于各种回调的场景。

^叫脱字符。

底层原理

block的内部数据结构

struct Block_layout {

      void *isa;  //类指针,实现对象相关功能

      int flags;   //按bit位表示附加信息

      int reserved;   //保留变量

      void (*invoke)(void *, ...);   //函数指针,指向具体的调用地址

      struct Block_descriptor *descriptor;   //附加的描述信息,如结构体大小以及copy和dispose函数的指针

      /* Variables */   //通过block或weak关键字引用的变量,通过复制到结构体中,block才能访问它外部的变量

}

种类型的block

_NSConcreteGlobalBlock:全局静态的block,不会访问外部变量(即没有Variables)

_NSConcreteStackBlock:栈中的block,函数返回时会被销毁

_NSConcreteMallocBlock:堆中的block,引用计数为0时销毁

clang -rewrite-objc block.c 可以对以上三种类型的block源码进行分析。

__main_block_impl_0是block的实现,ARC开启时,isa指向_NSConcreteGlobalBlock类型

impl指向__main_block_func_0对应invoke,descriptor描述附加信息(block引用外部变量会加入结构体,造成size增大)

__Block_byref_i_0结构体中保存了引用并要修改的变量(__main_block_impl_0中引用的也是__Block_byref_i_0结构体指针)

_NSConcreteMallocBlock通常不会在源码中出现,但当block被copy的时候,才会复制到堆中,需要手动release

注:对于block外引用的变量,默认将其复制到数据结构中来访问,所以block内部修改变量值无法影响block外部的变量;而对于用__block修饰的外部(局部)变量引用,是复制其引用地址来访问的,即把指针传给了结构体,所以block内部可以改变变量的值。

而对于全局变量或静态变量,由于只有一份内存,并未直接复制或把变量指针传给结构体,所以不用block也能实现内部更改变量的值。但是当block被copy时,引用的对象不会被release而造成循环引用,所以要使用__weak关键字

实际使用

声明并赋值

void (^testBlock)(id para1, id para2) = ^(id para1, id para2) { //do something } 

 别名定义法(可作为参数传递)

typedef void(^BlockName)(id para1);

@property (nonatomic, copy)BlockName block;//可以不用暴露,而作为方法的参数直接传递,如下

- (void)fetchMethod:(BlockName)block;

__block和__weak关键字

__block增加引用,使对象可以在block内修改、赋值,且不会被强引用造成循环引用。

__weak弱引用全局(self)变量,避免循环引用。__weak __typeof(&*self)weakSelf =self;

原理:__block在结构体中保存了变量的指针;__weak

与delegate的对比

1、block是让代码块以闭包(一个函数+其执行的外部上下文变量)的形式传递内容,实在是太轻量级了,适用于大多数异步和简单的回调。

2、当有多个方法回调时应当选用delegate会更清晰,如UITableView的delegate代理方法。

3、block会涉及到栈区到 堆区的拷贝等操作,delegate只是定义了一个方法列表,在遵守了协议的对象的objc_protocol_list中添加了一个节点,运行时向对象发送消息即可。所以block在时间空间消耗都大于delegate,性能消耗较大。

4、代理更加面向过程,block更加面向结果。

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

推荐阅读更多精彩内容