block的实现原理(二)
来源:互联网 发布:怎么让4g网络信号增强 编辑:程序博客网 时间:2024/05/16 04:31
OC代码:
int a=10;
void (^blk)(void) = ^(){
printf("This is a block.");
};
上面的OC代码被转化成了C语言的代码后,可以看出:block被转化成了指向__main_block_impl_0结构体的指针。这个结构体包含两个__block_impl和__main_block_desc_0两个结构体,和一个方法。
struct__main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int a;
//下面这个是结构体构造函数 ,用来初始化变量__block_impl impl
和__main_block_desc_0
__main_block_impl_0(void *fp,struct __main_block_desc_0 *desc,int _a, int flags=0):a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
OC被转化成了以下C语言代码:
int a=10;
void (*blk)(void) =(void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA,a);
简化的C语言代码:
void (*blk)(void) = &__main_block_impl_0(
(void *)__main_block_func_0,
&__main_block_desc_0_DATA
);
//__main_block_impl_0 函数 参数:参数1 __main_block_func_0指针参数2 __main_block_desc_0_DATA :描述结构体大小 参数3 就是block之外的变量 a
//__main_block_func_0函数,即block对应的函数体。该函数接受一个__cself参数,即对应的block自身。
static void__main_block_func_0(struct __main_block_impl_0 *__cself) {
int a=__cself->a;
printf("This is a block.");
}
struct __block_impl {
void *isa;//isa指针,如果我们对runtime了解的话,就明白isa指向Class的指针 (_NSConcreteStackBlock,_NSConcreteMallocBlock和_NSConcreteGlobalBlock)
int Flags;//Flags,当block被copy时,应该执行的操作
int Reserved;//Reserved为保留字段
void *FuncPtr;//FuncPtr指针,指向block内的函数实现
};
staticstruct __main_block_desc_0 {
size_t reserved;//reserved为保留字段默认为0
size_t Block_size;//Block_size为sizeof(struct __main_block_impl_0)
,用来表示block所占内存大小。因为没有持有变量,block大小为impl的大小加上Desc指针大小
} __main_block_desc_0_DATA = {0, sizeof(struct __main_block_impl_0)};
//__main_block_desc_0_DATA
为__main_block_desc_0的一个结构体实例
这个结构体,用来描述block的大小等信息。如果持有可修改的捕获变量时(即加__block
),会增加两个函数(copy和dispose)
OC代码:
blk();
转成C语言:
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
简化的C语言代码:
blk->FuncPtr(blk);block的创建和调用,可以看出执行block就是调用一个以block自身作为参数的函数,这个函数对应着block的执行体。
//如果一个block外部的变量加了 __block修饰系统就会创建一个结构体内部封装了变量的地址
__blockint a = 10;
//结构体__Block_byref_a_0的变量
struct __Block_byref_a_0 {
void *__isa;
__Block_byref_a_0 *__forwarding;//保存自己的地址,____forwarding,指向自己的指针,当从栈copy到堆时,指向堆上的block
int __flags;// 0
int __size; //当前结构体的大小
int a;
};
__attribute__((__blocks__(byref)))__Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a,0, sizeof(__Block_byref_a_0),10};
block的类型用_NSConcreteStackBlock来表示,表明这个block位于栈中。同样地,还有_NSConcreteMallocBlock和_NSConcreteGlobalBlock。
由于block也是NSObject,我们可以对其进行retain操作。不过在将block作为回调函数传递给底层框架时,底层框架需要对其copy一份。比方说,如果将回调block作为属性,不能用retain,而要用copy。我们通常会将block写在栈中,而需要回调时,往往回调block已经不在栈中了,使用copy属性可以将block放到堆中。或者使用Block_copy()和Block_release()。
- block的实现原理(二)
- Block的实现原理
- block的实现原理
- block的实现原理
- block的实现原理(整理)
- block的用法 实现原理
- Block的内部实现原理
- Objective-C的Block的实现原理
- Block的使用与实现原理
- block 实现原理(内存管理详解)(二)
- block的底层实现(二)
- block 实现原理
- block底层实现原理
- block实现原理详解
- block 实现原理详解
- Block实现原理
- Block实现原理
- block实现原理?
- kill 掉所有正在运行的hadoop jobs
- JForum框架结构和主要配置文件说明
- java 设计模式---创建对象
- 设计模式--23种模式精华(一)
- NLTK安装tips
- block的实现原理(二)
- 关于maven(持续更新)
- [Javascript]异步上传文件
- 我的科研生活2017-3-23
- 我的WCF之旅(4):WCF中的序列化[下篇]
- 常见Android面试题及答案(详细整理)
- PHP字符串处理
- Linux下apt方式卸载软件
- 面试记录