iOS Block 语法及底层实现

前言

        iOS开发的同学们肯定都用过block,对block 的运用熟练在我们开发过程中很有必要;在此我也对其进行一番解读,希望能在大家开发或者面试过程中有所帮助。

一、block 概要

1、什么是block

一句话:带有自动变量(局部变量)的匿名函数。 

Q1 什么 是匿名函数  度娘解释曰 ;

Q2 自动变量相关:C语言函数中可能用到的变量由自动变量、函数参数、静态变量、静态全局变量、全局变量;有兴趣的还可以去探究其内存中的存储域

二、block用法定义

1、block语法及变量

block 语法: ^ 返回值类型 参数列表 表达式 

^ (NSString *) (NSString *bookId){}

省略返回值写法:

^(void){};

省略返回值及参数写法:

^{};

2、block 实质

简单些一行block

声明一个block并打印

 void(^block)(void)=^{

        printf("block block \n");

    };

    block();

通过在终端命令行 clang -rewrite-objc 源代码文件名 ,会生成相应的.cpp文件,由C++编写的源文件。具体实现大家可以自己去操作一下我这里贴出一段类似代码:

C++ 源码文件中很多内容,只要看到截图的调用部分。

block实质也是一个oc对象,简单来说和class代码的设计思想是为其构建一个结构体struct,把结构体相应参数做索引,遵循一定的规则,去找到相应的实现方法;同样的我们在设计OC 对象时也应借助这个思想。无论对象怎么变化,他有一个基本的结构体单元。

三、block截获自动变量

1、block底层如何截获自动变量值

上文中讲到block实际是一个oc 对象,它就有isa指针、变量等对象属性,当执行block语句中有使用外部变量时,会将相应的变量值 自动声明并存储到block 的结构体当中去

2、blcok 捕获自动变量

__block 修饰词修饰变量,类似于static、auto 等c语言声明词,一经修饰,底层会做相应的处理;至于做了什么,要跟blcok 存储域有关。blcok类型 有三种 

栈上 NSConcreteStackBlock

堆上 NSConcreteMallocBlock

全局 NSConcreteGlobalBlock (存储在程序的数据区)

当使用的是栈上的block 时,你使用的又是局部变量,想截获变量改变其值,必须用__block 修饰,是将该变量变为一个结构体自动变量才能被修改,示例如下:

block_t=blk;

{

__block NSMutableArray *array=[[NSMutableArray alloc] init];

blk=^(NSObject obj){

    [array add object:obj];

}

blk([[NSObject alloc] init]);

}

或者这么写:

block_t=blk;

{

 NSMutableArray *array=[[NSMutableArray alloc] init];

blk=[^(NSObject obj){

[array add object:obj];

} copy]

blk([[NSObject alloc] init]);

}

这两种写法 都是 将变量array 从 栈copy 到 堆上,第一种是array 变量通过 block 修饰符生成一个forwarding指针,指向其拷贝到堆上的生成的自动变量结构体;第二种是把block 拷贝到堆上截获的变量也会被拷贝到堆上,这样当运行完大括号的代码时,array 也不会被释放,知道block 运行完成被释放时,array 才会跟着被释放释放是由系统调用dispose完成。

关于对象类型自动变量捕获,使用方法一还是方法二有个小总结:

1)block作为函数返回值返回时

2)将block赋值给类的附有__strong 修饰符的id 类型或block类型成员变量时

3)向方法名中含有usingBlock 的cocoa框架方法或GCD 的api 传递block 时;

除了以上几种情况外,其他都建议使用方法二。

由于以上变量都是 strong 类型变量,如果是weak 类型变量呢?类似如下:

block_t=blk;

{

__block NSMutableArray __weak *array=[[NSMutableArray alloc] init];

blk=^(NSObject obj){

    [array add object:obj];

}

blk([[NSObject alloc] init]);

}

经验证,运行完代码,在作用域外array 会被释放,array 不会有任何改变。

3、blcok循环引用

block 的循环引用是我们平时写代码经常要注意的问题,循环引用的原因即为 block 强持有该 自动变量,自动变量又强持有 blcok,运行完后释放时你等待我释放,我等待你释放,由此造成死循环;类似的有多线程中的死锁问题,二等待一运行完一等待二运行完导致两者都在等待执行卡死在那儿。如下图

循环引用示意图

避免循环引用的方式主要是两种:

1)使用__weak 或 __unsafe_unretained修饰自动变量使得blcok 弱持有 自动变量,当block 执行完后,blcok 和对象都能被释放

2)使用__block 修饰自动变量 , 但是 必须要调用 一次 block ,才能使得 block变量对 自动变量的持有释放,不然还是会有循环引用

4、blcok 拷贝/释放

有一个小点,显示调用copy 和release 的情况,是在非ARC 情况下即需要我们主动去调用release 方法 将copy 到堆里的block 释放掉,这里我不做详细描述,有兴趣的可以自己去度娘问问;

block 的使用博大精深,需要更进一步的探寻它的使用场景,期待与你一起深入学习研究。。。

参考:

1、<<Object-C 高级编程iOS 与OSX 多线程和内存管理>>

2、https://www.jianshu.com/p/6a7c498c42bc

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