block 介绍
带有自动变量(局部变量)的匿名函数。
函数多次调用中传值得变量有:
- 静态变量
- 静态全局变量s
- 全局变量
这一概念并不仅指Blocks,它还存在于其他许多程序语言中,在计算机科学中(闭包,lambda 计算)等;
模式
^void (int event) {
NSLog(@"This eventID: %d\n",event);
}
特点: 无函数名;带有“^”
自动变量值
截获自动变量值
(1)截获自动变量值
在定义(注意是定义,不是运行)时,局部变量base当前值被copy到栈上,作为常量供Block使用;
所谓的截获自动变量值本质是,执行Block语法时,Block语法表达式所使用的自动变量值被保存到Block的结构体实例中;将值传递给结构体的构造函数进行保存。
Block 的本质
clang -rewrite-objc 源代码文件名,
Block 结构体转化后展示: 栈上Block的结构体实例;
内存中的位置 Global,Stack,Malloc 几种类型区分;
block 对持有的对象的布局的顺序依然是强引用在前、弱引用在后;
Block 提供了将 Block 和 __block 变量从栈上复制到堆上的解决方案;解决因变量作用域的问题导致被遗弃的问题;
_block
__block 存储域类说明符,(typedef,extern,static,auto);
__block int value = 10;
结构体中的变量以10 为初始化的实例;原自动变量的成员变量;
栈上__block变量的结构体实例;
变量作用域 结束时,废弃;
__block变量的配置存储域 | Block从栈复制到堆的影响 |
---|---|
栈 | 从栈复制到堆并被Block持有 |
堆 | 被Block持有 |
循环引用
栈上的Block 什么时候会复制到堆 ?
- 调用Block的copy实例方法;
- Block 作为函数返回值返回时;
- 将Block赋值给附有 _strong修饰符id类型的类或Block类型成员变量时;
- 在方法中含有 usingBlcok的Cocoa框架或者 GCD的API 传递Block时;
其上所有本质为 Block_copy 函数被调用时 Block从栈复制到堆!
Block 中使用的赋值给附有_strong 修饰符的自动变量的对象和复制到堆上的 _block变量由于堆上的Block所持有,因而可超出变量的作用域而存在。
_weak 修饰符可以避免循环引用的发生;
__block 为避免循环引用必须执行block;这也是我们为什么一般选择 _weak而不是 _block 的原因;
注意问题:
在Block中使用成员变量,retain的不是这个变量,而会retain self;
另一个常见错误使用是,开发者担心retain cycle错误的使用__block;
_unsafe_unretained 会比weak出现野指针的问题,所以;
weak 在变量被释放的时候,赋值为 nil;
无论blk在堆上还是栈上,作为参数的Block不会发生copy。
解决方案
- 打开Xcode,给性能分析(profiling)编译。
- 载入Instruments。
- 使用应用程序,尝试尽可能多的重现场景和行为。
- 查看内存和泄露。
- 追踪内存泄露的根源。
FBRetainCycleDetector、FBAllocationTracker、FBMemoryProfiler。
在一个有向无环图(directed acyclic graph)中找环, 而节点就是对象,边就是对象之间的引用(如果对象A持有对象B,那么,A到B之间就存在着引用)。我们的 Objective-C 对象已经在我们的图中,我们要做的就是用深度优先搜索遍历它。
网友评论