
一、block本质:





二、变量捕获
auto :自动变量(局部变量),离开作用域就会销毁。 (我们声明的变量 auto int age=10默认前面有一个关键字auto)

1、auto变量捕获


变量捕获C++源码分析:




2、static变量捕获

C++源码分析


3、全局变量不捕获,直接根据地址使用

C++源码分析:

总结:
- 1.局部变量会捕获,全局变量不会捕获。
三、block的类型

- 程序区域:用来存放程序所有代码
- 数据区域:存放全局变量。(NSGlobalBlock放在该区域)
- 堆:堆是动态分配内存,调用alloc 或者malloc()申请内存,需要程序员申请内存,也需要程序员自己管理内存。(NSMallocBlock放在该区域)
- 栈:存放局部变量,系统自动管理内存。(NSStackBlock放在该区域)
- 程序区域和数据区域不需要我们管理,是编译器自己决定的,程序一启动时就将代码和数据搬到内存中,






四、在ARC环境下会对block自动进行copy操作的几种情况

- 1、block作为函数返回值时会进行copy操作


-
2、将block赋值给__strong指针时会进行copy操作

- 3、block作为Cocoa API中方法含有usingBlock的方法参数时会进行copy操作


- 4、block作为GCD API的方法参数时会进行copy操作

五、对象类型的auto变量
栈空间的block不会保住对象类型auto变量的命,如果是堆空间的block会保住对象类型auto变量的命。


-
1、如果对象auto变量是强指针,那么block就会强引用该对象
源码分析:




-
2、如果对象auto变量是弱引用,那么block就会弱引用该对象
源码分析:



六、block修改变量



证明如下:被__block修饰的age是__Block_byref_a_0对象的成员变量age



第二种方法:

#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的内存管理




八、__block修饰的对象类型


-
1、强引用
C++源码分析:


-
2、弱引用
八、block的循环引用




网友评论