![](https://img.haomeiwen.com/i6434429/305a83fd76042797.png)
一、block本质:
![](https://img.haomeiwen.com/i6434429/09757b1d025cd4d0.png)
![](https://img.haomeiwen.com/i6434429/4d84a93c3cf1b626.png)
![](https://img.haomeiwen.com/i6434429/d856b38470de5739.png)
![](https://img.haomeiwen.com/i6434429/c8d4e53930e1c0e0.png)
![](https://img.haomeiwen.com/i6434429/6685ed43dcfe829d.png)
二、变量捕获
auto :自动变量(局部变量),离开作用域就会销毁。 (我们声明的变量 auto int age=10默认前面有一个关键字auto)
![](https://img.haomeiwen.com/i6434429/53ee42749708b879.png)
1、auto变量捕获
![](https://img.haomeiwen.com/i6434429/157f898a484a8863.png)
![](https://img.haomeiwen.com/i6434429/db60fd1511a01986.png)
变量捕获C++源码分析:
![](https://img.haomeiwen.com/i6434429/4709265f339e3075.png)
![](https://img.haomeiwen.com/i6434429/5df554b3edfa8581.png)
![](https://img.haomeiwen.com/i6434429/ea358632a3837169.png)
![](https://img.haomeiwen.com/i6434429/3e96b190ed0fc9e0.png)
2、static变量捕获
![](https://img.haomeiwen.com/i6434429/e0b534497c33dfab.png)
C++源码分析
![](https://img.haomeiwen.com/i6434429/55a1d8db5827a01f.png)
![](https://img.haomeiwen.com/i6434429/fff535e6abb33155.png)
3、全局变量不捕获,直接根据地址使用
![](https://img.haomeiwen.com/i6434429/4ae128b2415518ec.png)
C++源码分析:
![](https://img.haomeiwen.com/i6434429/04218557e4592d20.png)
总结:
- 1.局部变量会捕获,全局变量不会捕获。
三、block的类型
![](https://img.haomeiwen.com/i6434429/14557575436248ca.png)
- 程序区域:用来存放程序所有代码
- 数据区域:存放全局变量。(NSGlobalBlock放在该区域)
- 堆:堆是动态分配内存,调用alloc 或者malloc()申请内存,需要程序员申请内存,也需要程序员自己管理内存。(NSMallocBlock放在该区域)
- 栈:存放局部变量,系统自动管理内存。(NSStackBlock放在该区域)
- 程序区域和数据区域不需要我们管理,是编译器自己决定的,程序一启动时就将代码和数据搬到内存中,
![](https://img.haomeiwen.com/i6434429/e313110b96b195d6.png)
![](https://img.haomeiwen.com/i6434429/773939c96b9cc65b.png)
![](https://img.haomeiwen.com/i6434429/73e2e091bf4bf1f3.png)
![](https://img.haomeiwen.com/i6434429/ab0dd1e3faf76593.png)
![](https://img.haomeiwen.com/i6434429/eed12cfd46f8b3bf.png)
![](https://img.haomeiwen.com/i6434429/71788aa88ff8f791.png)
四、在ARC环境下会对block自动进行copy操作的几种情况
![](https://img.haomeiwen.com/i6434429/f69e70bdc7bdbb47.png)
- 1、block作为函数返回值时会进行copy操作
![](https://img.haomeiwen.com/i6434429/b1a3a02f1bc35e80.png)
![](https://img.haomeiwen.com/i6434429/589981af485d98b0.png)
-
2、将block赋值给__strong指针时会进行copy操作
![](https://img.haomeiwen.com/i6434429/7f9da3d849f2f319.png)
- 3、block作为Cocoa API中方法含有usingBlock的方法参数时会进行copy操作
![](https://img.haomeiwen.com/i6434429/b630031640ae5864.png)
![](https://img.haomeiwen.com/i6434429/fa1e3d0196731383.png)
- 4、block作为GCD API的方法参数时会进行copy操作
![](https://img.haomeiwen.com/i6434429/ec0b5553f2a0aadb.png)
五、对象类型的auto变量
栈空间的block不会保住对象类型auto变量的命,如果是堆空间的block会保住对象类型auto变量的命。
![](https://img.haomeiwen.com/i6434429/e9312797b78b8a2b.png)
![](https://img.haomeiwen.com/i6434429/239da4483d36533b.png)
-
1、如果对象auto变量是强指针,那么block就会强引用该对象
源码分析:
![](https://img.haomeiwen.com/i6434429/f0f331fedd823309.png)
![](https://img.haomeiwen.com/i6434429/6cd3b28cf93bf910.png)
![](https://img.haomeiwen.com/i6434429/cae46f5af0fa6fe5.png)
![](https://img.haomeiwen.com/i6434429/3a339d43a1940580.png)
-
2、如果对象auto变量是弱引用,那么block就会弱引用该对象
源码分析:
![](https://img.haomeiwen.com/i6434429/a7785aa7d70f60a0.png)
![](https://img.haomeiwen.com/i6434429/e195cfa52b5136a3.png)
![](https://img.haomeiwen.com/i6434429/8b6bdadc4a9ea080.png)
六、block修改变量
![](https://img.haomeiwen.com/i6434429/27e5d68eb8a14cb3.png)
![](https://img.haomeiwen.com/i6434429/502d1eb0e417c1af.png)
![](https://img.haomeiwen.com/i6434429/0d236f5534cb45dd.png)
证明如下:被__block修饰的age是__Block_byref_a_0对象的成员变量age
![](https://img.haomeiwen.com/i6434429/9b875344116fbb32.png)
![](https://img.haomeiwen.com/i6434429/3ae16d4c4812b263.png)
![](https://img.haomeiwen.com/i6434429/6c31f983564cba7c.png)
第二种方法:
![](https://img.haomeiwen.com/i6434429/72d32b64f5efd631.png)
#import <Foundation/Foundation.h>
typedef void (^MJBlock) (void);
struct __Block_byref_age_0 {
void *__isa;
struct __Block_byref_age_0 *__forwarding;
int __flags;
int __size;
int age;
};
struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(void);
void (*dispose)(void);
};
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
struct __Block_byref_age_0 *age;
};
int main(int argc, const char * argv[]) {
@autoreleasepool {
__block int age = 10;
MJBlock block = ^{
age = 20;
NSLog(@"age is %d", age);
};
struct __main_block_impl_0 *blockImpl = (__bridge struct __main_block_impl_0 *)block;
NSLog(@"%p", &age);
}
return 0;
}
七、__block的内存管理
![](https://img.haomeiwen.com/i6434429/d6abd6a36c324896.png)
![](https://img.haomeiwen.com/i6434429/77b279974d1fc406.png)
![](https://img.haomeiwen.com/i6434429/579f85b32293bb9c.png)
![](https://img.haomeiwen.com/i6434429/4b38a8a42007a0ef.png)
八、__block修饰的对象类型
![](https://img.haomeiwen.com/i6434429/4778bb5668bab164.png)
![](https://img.haomeiwen.com/i6434429/d4319d0a8f6375b9.png)
-
1、强引用
C++源码分析:
![](https://img.haomeiwen.com/i6434429/6c322449c679764f.png)
![](https://img.haomeiwen.com/i6434429/2f4a8b7728ee9a4e.png)
-
2、弱引用
八、block的循环引用
![](https://img.haomeiwen.com/i6434429/3cb63e9218599f93.png)
![](https://img.haomeiwen.com/i6434429/807cafee25bff4d3.png)
![](https://img.haomeiwen.com/i6434429/42c8be796694eb0b.png)
![](https://img.haomeiwen.com/i6434429/66c92f61c4badf46.png)
网友评论