Object-C语言Block的实现方式
clang -rewrite-objc main.m
如果Xcode版本较高,可能会出现报错:
./block_VC.h::: fatal error: 'UIKit/UIKit.h' file not found
此时可尝试另一个命令:
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
Block的基本概念
1.没有捕获任何局部变量的block为_NSConcreteGlobalBlock,它以static函数的形式存储在代码区
2.捕获了局部变量的block为_NSConcreteStackBlock
3.当_NSConcreteStackBlock出现上面四种情况时,会变成_NSConcreteMallocBlock。(注意此时是调用了Block_Copy函数后)
Block编译后结果分析
基本类型变量
OC源码:
NSInteger age = ;
void(^completeBlock)(NSString *) = ^(NSString *name) {
NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age];
NSLog(@"%@",info);
}; completeBlock(@"jack");
编译后的C\C++源码:
// __block_impl为block的基础struct
//1.*isa:当前block对象所属的类型(注意:在OC语言中带有isa指针的都是对象)
//2.Flags:标示位,当类型为NSConcreteMallocBlock时,表示需要ARC内存管理,其他默认不需要内存管理
//3.Reserved:预留标示位,暂时不管它
//4.block的实际static内部函数地址指针
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
}; // __main_block_impl_0为block的最终struct
//1.impl:为上面的__block_impl结构体实例
//2.Desc:为block的描述结构体__main_block_desc_0,里面包含了block结构体的信息描述,在下面讲解
//3.age:从外面补货的变量,block采用的方式是直接在block实例中定义一个变量,将捕获的值赋给它
//4.__main_block_impl_0:为block结构体的构造函数,参数中包含从外面捕获的变量值
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
NSInteger age;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSInteger _age, int flags=) : age(_age) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
}; //__main_block_func_0为block具体实现的函数载体,具体的block的任务实现在此函数内
//参数:1是block的实例指针,2是block的外部传参name
static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) {
//从block实例中获取age变量的值
NSInteger age = __cself->age; // bound by copy //生成字符串NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age];
NSString *info = ((NSString * _Nonnull (*)(id, SEL, NSString * _Nonnull, ...))(void *)objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithFormat:"), (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_0, (NSString *)name, (NSInteger)age); //打印NSLog(@"%@",info);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_1,info);
} //reserved:保留字0
//Block_size:block实例在内存中占据内存大小
//__main_block_desc_0_DATA:默认desc结构体实例
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { , sizeof(struct __main_block_impl_0)}; //main函数
int main(int argc, char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; NSInteger age = ;
void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age)); ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_2); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class"))));
}
}
block简单结构布局
struct __block_impl
struct __main_block_impl_0
static void __main_block_func_0
static struct __main_block_desc_0
__block NSInteger age = ;
void(^completeBlock)(NSString *) = ^(NSString *name) {
NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age];
NSLog(@"%@",info);
}; completeBlock(@"jack");
struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};
//age的block变量实例__Block_byref_age
//__isa:age的block变量实例所属的类型
//__forwarding:age的block变量实例的指针
//__flags:变量是否被内存管理标示
//__size:所占内存大小
//age:age变量值
struct __Block_byref_age_0 {
    void *__isa;
    __Block_byref_age_0 *__forwarding;
    int __flags;
    int __size;
    NSInteger age;
};
//原来的age变量值,变成了__Block_byref_age_0变量指针
struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    __Block_byref_age_0 *age; // by ref
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=) : age(_age->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) {
    //通过block实例获取变量的指针
    __Block_byref_age_0 *age = __cself->age; // bound by ref
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_7acc63_mi_0,name,(age->__forwarding->age));
}
//当block从栈复制到堆上时,会对__Block_byref_age_0变量进行拷贝,也会从栈拷贝到堆上
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->age, (void*)src->age, /*BLOCK_FIELD_IS_BYREF*/);}
//__Block_byref_age_0变量的析构函数,当block实例的引用计数为0时,是否__Block_byref_age_0变量的内存空间
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->age, /*BLOCK_FIELD_IS_BYREF*/);}
//desc结构体中新增了copy函数和dispose函数指针
static struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
    void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { , sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        //block变量实例
        __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*),(__Block_byref_age_0 *)&age, , sizeof(__Block_byref_age_0), };
        //block实例
        void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age, ));
        ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_7acc63_mi_1);
        return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class"))));
    }
}
简单结构布局
struct __block_impl
struct __main_block_impl_0
static void __main_block_func_0
static struct __main_block_desc_0
//新增
struct __Block_byref_age_0
static void __main_block_copy_0(
static void __main_block_dispose_0(
__block NSInteger age = 10;后,在简单布局结构中新增了3项
struct __Block_byref_age_0
static void __main_block_copy_0(
static void __main_block_dispose_0(
OC源码:
NSMutableArray *friends = [NSMutableArray array];;
void(^completeBlock)(NSString *) = ^(NSString *name) {
NSLog(@"%@--%@",name,friends);
}; completeBlock(@"jack");
编译后的C\C++源码:
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;
    NSMutableArray *friends;
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSMutableArray *_friends, int flags=) : friends(_friends) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) {
    NSMutableArray *friends = __cself->friends; // bound by copy
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_1b4a2f_mi_0,name,friends);
}
//block实例从栈复制到堆上时,将指针变量引用计数加一
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->friends, (void*)src->friends, /*BLOCK_FIELD_IS_OBJECT*/);}
//block实例引用计数为0时,析构指针变量对象
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->friends, /*BLOCK_FIELD_IS_OBJECT*/);}
static struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
    void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { , sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        NSMutableArray *friends = ((NSMutableArray * _Nonnull (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("array"));;
        void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, friends, ));
        ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_1b4a2f_mi_1);
        return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class"))));
    }
}
简单结构布局
struct __block_impl
struct __main_block_impl_0
static void __main_block_func_0
static struct __main_block_desc_0
static void __main_block_copy_0(
static void __main_block_dispose_0(
__block指针类型变量
OC源码:
__block NSMutableArray *friends = [NSMutableArray array];;
void(^completeBlock)(NSString *) = ^(NSString *name) {
NSLog(@"%@--%@",name,friends);
}; completeBlock(@"jack");
编译后的C\C++源码:
struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};
//__Block_byref_friends_0结构体实例中包含了friends指针
//并且多了__Block_byref_id_object_copy函数:对friends进行copy
//多了__Block_byref_id_object_dispose函数:对friends进行析构
struct __Block_byref_friends_0 {
    void *__isa;
    __Block_byref_friends_0 *__forwarding;
    int __flags;
    int __size;
    void (*__Block_byref_id_object_copy)(void*, void*);
    void (*__Block_byref_id_object_dispose)(void*);
    NSMutableArray *friends;
};
struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    __Block_byref_friends_0 *friends; // by ref
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_friends_0 *_friends, int flags=) : friends(_friends->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) {
    __Block_byref_friends_0 *friends = __cself->friends; // bound by ref
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_252d0c_mi_0,name,(friends->__forwarding->friends));
}
//block实例从栈复制到堆上时,__block变量结构体实例将指针变量引用计数加一,同时__block变量结构体实例内的NSMutableArray *friends变量也递归加一
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->friends, (void*)src->friends, /*BLOCK_FIELD_IS_BYREF*/);}
//block实例引用计数为0时,__block变量结构体实例被析构,同时__block变量结构体实例内的NSMutableArray *friends变量也递归析构
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->friends, /*BLOCK_FIELD_IS_BYREF*/);}
static struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
    void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { , sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        __attribute__((__blocks__(byref))) __Block_byref_friends_0 friends = {(void*),(__Block_byref_friends_0 *)&friends, , sizeof(__Block_byref_friends_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSMutableArray * _Nonnull (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("array"))};;
        void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_friends_0 *)&friends, ));
        ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_252d0c_mi_1);
        return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class"))));
    }
}
简单结构变量
struct __block_impl
struct __main_block_impl_0
static void __main_block_func_0
static struct __main_block_desc_0
static void __main_block_copy_0(
static void __main_block_dispose_0(
//新增
struct __Block_byref_age_0
//局部变量
__block NSMutableArray *friends = [NSMutableArray array];;
void(^completeBlock)(NSString *) = ^(NSString *name) {
NSLog(@"%@--%@",name,friends);
}; (lldb) expression -P -- completeBlock
(void (^)(NSString *)) $ = 0x000000010a061130 {
__isa = __NSMallocBlock__
__flags = -
__reserved =
__FuncPtr = 0x000000010a061130 (iOS_KnowledgeStructure`__main_block_invoke at main.m:) {}
}
利用clang转换后的C\C++源码
struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    __Block_byref_friends_0 *friends; // by ref
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_friends_0 *_friends, int flags=) : friends(_friends->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};
static void *_Block_copy_internal(const void *arg, const int flags) {
struct Block_layout *aBlock;
const bool wantsOne = (WANTS_ONE & flags) == WANTS_ONE;
//
if (!arg) return NULL;
//
aBlock = (struct Block_layout *)arg;
//
if (aBlock->flags & BLOCK_NEEDS_FREE) {
// latches on high
latching_incr_int(&aBlock->flags);
return aBlock;
}
//
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
return aBlock;
}
//
struct Block_layout *result = malloc(aBlock->descriptor->size);
if (!result) return (void *);
//
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
//
result->flags &= ~(BLOCK_REFCOUNT_MASK); // XXX not needed
result->flags |= BLOCK_NEEDS_FREE | ;
//
result->isa = _NSConcreteMallocBlock;
//
if (result->flags & BLOCK_HAS_COPY_DISPOSE) {
(*aBlock->descriptor->copy)(result, aBlock); // do fixup
}
return result;
}
Object-C语言Block的实现方式的更多相关文章
- object - c 语言基础  进阶笔记  随笔笔记
		重点知识Engadget(瘾科技)StackOverFlow(栈溢出)Code4Apprespon魏先宇的程序人生第一周快捷键: Alt+上方向键 跳到最上面 Alt+下方向键 跳到最下面 ... 
- OC语言BLOCK和协议
		OC语言BLOCK和协议 一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相似 ... 
- Object Pascal 语言基础
		Delphi 是以Object Pascal 语言为基础的可视化开发工具,所以要学好Delphi,首先要掌握的就是Object Pascal 语言.Object Pascal语言是Pascal之父在1 ... 
- 李洪强iOS开发之OC语言BLOCK和协议
		OC语言BLOCK和协议 一.BOLCK (一)简介 BLOCK是什么? 苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相 ... 
- OC语言Block 续
		OC语言 Block 转载:http://blog.csdn.net/weidfyr/article/details/48138167 1.Block对象中的变量行为 结论: 在block代码块内部可 ... 
- OC语言Block
		OC语言Block 一.Block (一)简介 Block是什么?苹果推荐的比较特殊的数据类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. Block和 ... 
- OC语言-block and delegate
		参考博客 OC语言BLOCK和协议 iOS Block iOS Block循环引用精讲 iOS之轻松上手block 深入浅出Block的方方面面 Block apple官方参考 1.定义一个block ... 
- 第二百五十九节,Tornado框架-模板语言的三种方式
		Tornado框架-模板语言的三种方式 模板语言就是可以在html页面,接收逻辑处理的self.render()方法传输的变量,将数据渲染到对应的地方 一.接收值渲染 {{...}}接收self.re ... 
- set object is not JSON serializable 解决方式
		python return json的时候报错: set object is not JSON serializable 解决方式,增加一个将set转为list的函数: def set_default ... 
随机推荐
- Android 广播代码的发送与接收
			Android四大组件之一广播,使用的也比较多,广播可大致分为两种,一种是Android系统区域的广播,是由系统指令发出,例如:点亮屏幕广播,开机过程中的一些广播 省略-, 然而还有一种广播就是我们自 ... 
- Windows.Web.Http.HttpClient.GetStringAsync 总是返回相同的结果
			今天在测试博客园新闻WP8.1客户端的时候,发现电脑上浏览的新闻已经更新了.但手机上的还没更新,于是想到肯定是有bug了.于是建了一个Web测试项目,发现只有第一次发出了请求.一开始以为是MVVM的问 ... 
- C#不用union,而是有更好的方式实现
			用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C#为什么没有这个关键字呢?怎么实现这个功能?其实 ... 
- NetCore入门篇:(七)Net Core项目使用Controller之二
			一.简介 1.说明Post,Get定义的区别. 2.说明如何路由定义. 二.Get.Post定义 1.api不定义访问方式时,同时支持get 和 post.如果定义某种方式,则仅支持某种方式.具体看代 ... 
- 使用Git上传代码到远程仓库
			1.进入文件夹,cd f:/test/ 2.初始化远程仓库,git init 3.添加代码,git add . (注意add后面的点前面有一个空格) 4.提交代码到远程仓库,git commit -m ... 
- WinForm ListView不分页加载大量数据
			WinForm的ListView在加载大量数据时会出现闪烁的问题,同时数据加载很慢.如果你的列表中有超过千条的数据且不做特殊处理还是用普通的ListView.Items.Add(),估计你的用户得抱怨 ... 
- FreePascal - CodeTyphon交叉编译,在一个操作系统生成各个操作系统可以运行的程序!
			致谢:[XE3]MN,让我加快完成了使用CodeTyphon进行交叉编译! CodeTyphon版本: 6.0 下载:http://www.pilotlogic.com/codetyphon/zips ... 
- 使用pipreqs生成项目依赖
			作用 导出当前项目的环境依赖 使用 # 安装 pip3 install pipreqs # 导出项目环境依赖 pipreqs ./ # 如果是Windows系统,会报编码错误 (UnicodeDeco ... 
- iOS 卡顿
			1 使用 dispatch_async,也可能会出现卡顿. 由于mac系统允许overcommit,而iOS系统不允许overcommit 故要控制GCD队列的数量并且最好设置target queue ... 
- $_SERVER[]数组解析
			$_SERVER['PHP_SELF'] 将会得到 /test.php/foo.bar 这个结果.__FILE__ 常量包含当前(例如包含)文件的绝对路径和文件名. 如果 PHP 以命令行方式运行,该 ... 
