[iOS]block详解

1、block简介

block字面意思就是代码块

iOS4.0 Apple引入的特性

block是Objective C语言中的对象 但是与NSObject有所区别 block是特殊的Objective C对象

block 对象提供了一个使用 C 语言和 C 派生语言(如 Objective-C 和 C++)来创建表达式作为一个特别的函数。在其他语言和环境中,一个block对象有时候被称为“闭包(closure)”。在这里,它们通常被口语化为”块(blocks)”,除非在某些范围它们容易和标准 C 表达式的块代码混淆。

对于闭包(closure),有很多定义,其中闭包就是能够读取其它函数内部变量的函数

(以上内容了解)

“^”符号可以称为caret['kærət]也叫脱字符 插入符

返回值(^块对象名称)(参数列表类型) = ^(参数列表){块对象中的代码};

2、用处

1)简单的回调过程,不用再实现并调用某个函数 (UIView动画)

2)代码简洁,减少冗余代码

3)与GCD结合使用 爽爆了

3、block的声明、使用

声明block

block实现

调用block(代码的执行顺序)

typedef声明 简称typedef 为现有类型创建一个新的名字,或称为类型别名,在结构体定义,还有一些数组等地方都会用到

block作为属性 使用copy

方法参数为block

(简单了解)返回值为block 返回值block的类型要typedef

4、系统方法使用block 以及 系统方法内部的实现、实现两个自定义类

动画、present

blockButton

block和代理

snippet 代码片段

5、block中变量存取管理

1)Static修饰符的或全局变量

因为全局变量或静态变量在内存中的地址是固定的,block在读取该变量值的时候是直接从其所在内存读出,获取到的是最新值,而不是在定义代码块时copy的常量.

2)局部变量

局部变量 在block中只读, block定义时copy变量的值,在block中作为常量使用,所以即使变量的值在block外改变,也不影响它在block中的值

3)__block修饰的变量

如果要在block内修改block外声明的局部变量,那么一定要对该变量加__block标记

block变量,被__block修饰的变量称作block变量

6、block自身的内存管理

block是默认建立在栈上, 所以如果离开方法作用域, block就会被丢弃

非ARC下

只要实现一个对周围变量没有引用的block,就会显示为是NSGlobalblock

如果其中加入了对周围变量的引用,就是NSStackblock

如果你对一个NSStackblock对象使用了block_copy()或者发送了copy消息,就会得到NSMallocblock

1)NSGlobalblock:retain、copy、release操作都无效;

2)NSStackblock:retain、release操作无效,必须注意的是,NSStackblock在函数返回后,block内存将被回收。即使retain也没用。容易犯的错误是[mutableAarry addObject:stackblock],在函数出栈后,从mutableAarry中取到的stackblock已经被回收,变成了野指针。正确的做法是先将[stackblock copy]到堆上,然后加入数组:[mutableAarry addObject:[[stackblock copy]]。支持copy,copy之后生成新的NSMallocblock类型对象。(补:在ARC中不用担心此问题,因为ARC中会默认将实例化的block拷贝到堆上)

3)NSMallocblock支持retain、release,虽然打印的retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain;

block的copy、retain、release操作不同于NSObject的copy、retain、release操作:

4)block_copy与copy等效,block_release与release等效;

5)对block不管是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1;

6)尽量不要对block使用retain操作,不方便管理。

7、block对block中使用的obj对象的内存管理

staticObj、instanceObj、localObj、blockObj多种类型obj对象

主要是block被copy时其块中用到的变量的引用计数

1)非ARC

staticObj在内存中的位置是确定的,所以block copy时引用计数不会改变。

instanceObj在block copy时并没有直接让instanceObj对象本身引用计数加1,但却让self引用计数加1。所以在block中可以直接读写instanceObj变量。

localObj在block copy时,系统自动增加其引用计数指针复制。

blockObj在block copy时引用计数也不会改变。

使用__block避免循环引用 __block 类 *对象 = self

void(^block)(void)= ^{

[blockSelf doSomething];

};

7、循环引用retain cycle

循环引用指两个对象相互强引用了对方,即retain了对方,从而导致谁也释放不了谁的内存泄露问题。如声明一个delegate时一般用assign而不能用retain或strong,因为你一旦那么做了,很大可能引起循环引用

释放second 在fist delloc中释放 fist的delloc什么时候执行呢 fist引用计数为0时执行 然而现在即便是将fist从window.rootViewController上卸载下来 即释放一次 却发现second还保留着first的一次引用 到头来还是要释放second 形成了delegate版本的retain cycle 即循环引用

释放_pblock 在viewController delloc中释放 delloc什么时候执行呢 viewController引用计数为0时执行 然而现在即便是将viewController从window.rootViewController上卸载下来 即释放一次 却发现_pblock还保留着viewController的一次引用 到头来还是要释放_pblock 形成了block版本的retain cycle 即循环引用

block在ARC下的内存管理

ARC下

在ARC下, 以下几种情况, block会自动被从栈复制到堆:

1.被执行copy方法

2.作为方法返回值

3.将block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时

4.在方法名中含有usingblock的Cocoa框架方法或者GCD的API中传递的时候.

block中的对象的内存管理

ARC下

只有在使用local变量时,block会复制指针,且强引用指针指向的对象一次。其它如全局变量、static变量、block变量等,block不会拷贝指针,只会强引用指针指向的对象一次。

block的循环引用,因为block在拷贝到堆上的时候,会retain其引用的外部变量,那么如果block中如果引用了它的宿主对象,那很有可能引起循环引用。如:self.myblock = ^{[selfdoSomething];};

使用__weak避免循环引用

__weak typeof(ViewController *) weakSelf = self

self.myblock = ^{[weakSelfdoSomething];}

Tips:

内存主要分为

1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。

2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。

4、文字常量区 —常量字符串就是放在这里的。程序结束后由系统释放。

5、程序代码区—存放函数体的二进制代码。

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

推荐阅读更多精彩内容

  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 1,953评论 1 16
  • 1、概述 闭包 = 一个函数「或指向函数的指针」+ 该函数执行的外部的上下文变量「也就是自由变量」;Block 是...
    DeerRun阅读 660评论 0 0
  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,804评论 10 69
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 2,004评论 0 12
  • 一、Objective-C发展史 Objective-C从1983年诞生,已经走过了30多年的历程。随着时间的推移...
    没事蹦蹦阅读 5,819评论 12 34