Block


此处是文章概述


基础使用篇

什么是Block

定义及理解

Block是C语言的扩充功能,用一句话来概括就是:带有局部变量的匿名函数;
当我们用面向对象的思想,来看待Block时,又可以理解为:
Block是将函数执行体及其上下文封装起来的对象
那么,从上面的定义就不难理解,Block本质是一个OC对象,这个对象封装了一个函数的执行体(即函数的实现)和函数的执行上下文(即函数的参数及返回值);
注:Block是对象这点在下文原理分析时会得以证明;

范式

下图是Block的BN范式的抽象表示:


Block BN 范式.jpg

从图中可以看出,Block由标识符^、返回值、参数、表达式四部分组成,而从这个范式来看,Block和C语言函数极为相似,两者只有细微的差别:C语言的函数名变成了Block的标识符^; 除此之外,语法上基本一致,那么我们就可以拿C语言函数来类比的去理解Block的模式;
熟悉C语言的一定会知道,C语言函数中,返回值和参数都不是必须存在的部分,比如:

void func()
{
    printf("Hello World")
}

上述示例中,就省去了参数和返回值这两个模块,那么剩下必须要存在的模块即为:函数名、表达式;
那么同样来理解Block,其中Block的参数和返回值也可以不存在,那么对应到上图中,黑色的两个部分 ^表达式 是必须存在的,而返回值参数是不一定存在的;

基础使用及最佳实践

在上一节中,我们看了Block的BN范式,那么这一节,再来看一下Block的基础使用,以及在日常使用过程中的一些最佳实践;

基本使用

在日常开发中,如果我们想使用一个Block去处理一些逻辑,我们可以像以下那样去使用:

int (^sum)(int a, int b) = ^ int (int a, int b){
        
        return a + b;
    };

上述例子中,我们定义了一个名称为sum的Block,使用时只需要如下调用即可
int sums = sum(10, 20)
但是这种使用往往需要在OC的方法中定义 并且调用,超出方法作用域之后则不能再使用,故使用场景并不是太多,正因如此,才引出了下边的作为属性的用法;

作为属性

将Block作为属性调用时,不仅解决了Block作用域的问题,还可以在别的类中使用;但在使用过程中,我们需要注意当Block作为属性的时候,属性关键字的使用:此处应为copy;

作为参数

在日常开发中,Block作为参数使我们使用频率最高的一种情形,例如以下情况:

- (void)startRequestWithParams:(NSDictionary *)prames completion:(void(^)(BOOL isSuccess, NSDictionary *result))completion;
[agent startRequestWithParams:prames completion:^(BOOL isSuccess, NSDictionary *result ){
    // do something 
}];

以上是一个我们常用的网络请求的示例,这里将Block作为方法的参数进行了传递,这样做有以下好处:

  • 降低了代码的分散程度
  • 集约型的处理一块逻辑,更利于代码查看和维护

作为返回值

在日常开发中,我们自己把Block作为返回值的情况是比较少的,但是我们也是需要去了解一下当Block作为返回值使用时,是什么样式;在布局库Mssonry中大量的使用了Block作为返回值;如常用的的

- (MASConstraint * (^)(id attr))equalTo;
- (MASConstraint * (^)(CGFloat offset))offset;

那么上述两个方法的使用,如下:

make.equalTo(someObj).offset(10)

从这里可以发现,当Block作为返回值时,可以很连贯的组成链式调用,在一些场景很适合,但在大部分场景下,Block作为返回值时写出的代码比较难以理解,这可能也是使用较少的一个原因吧~

最佳实践

每个Block都有自己固定的类型,也正是因为这样才可以赋值给适当类型的变量,这个类型就是根据Block的参数返回值决定的;那么。也就有了以下这种Block的用法:

int (^sum)(int a, int b) = ^ int (int a, int b){
        
        return a + b;
    };

但是在使用时,不难发现这种用法,和我们在正常定义变量时有差别,Block的变量名被包含在了中间位置,放在了类型之中,这和id obj = [NSObject new] 这样的定义方式不一样,这样的语法让人难以记住,并且难以理解;
在Block定义一节有提到,Block本质是一个OC对象,那么能不能也像对象一样使用,为了方便使用和理解,我们可以使用定义别名的方式,给Block定义一个易于记住的别名,将Block的类型隐藏在其后面,那我们就可以使用C语言中的** 类型定义 **来解决,示例如下:

typedef int (^SumBlock)(int a, int b);

这样一来,就不用复杂的类型来创建变量了,直接用新类型即可:

SumBlock sum  = ^ int (int a, int b){
        
        return a + b;
    };

这样就符合了类型在前,变量在后的习惯了,通过这个特性,网络请求的方法也可以变得简洁起来:

typedef void (^CompletionBlock)(BOOL isSuccess, NSDictionary *result);

- (void)startRequestWithParams:(NSDictionary *)prames completion:(CompletionBlock)completion;

变量的截获

局部变量

  • 基本数据类型:截获其值
  • 对象类型:连同对象所有权修饰符一起截获

静态局部变量

以指针的形式截获

全局变量 & 静态全局变量

不截获

__block关键字

循环引用问题


内部原理篇

Block的本质

Blocks捕获变量的内部实现

__block关键字的实现原理

Block存储域


总结

此处是总结


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