位置: 主页 > 网页游戏公益服 >

老生常谈之Block

clang -rewrite-objc main.m

你会发现在当前文件夹下生成了一个.cpp文件,它是经过clang编译器编译之后的文件,打开之后里面大概有5百多行,其实我们看下面的这些代码就足够了:

还有一种情况是Global的block:

其中包含三个结构体:

如果两个block(block1,block2)同时都是用 __ block变量,如果block1被复制到了堆上,那么 __ block变量也会在block1复制到堆的同时复制到堆上,当block2再是用到 __ block变量的时候,只是增加堆上 __ block变量的引用计数,不会再次复制。如果堆上的block1和block2被废弃了,那么它所是用的 __ block变量也就被释放了(如果block1被废弃,而block2没有被废弃,那么 __ block变量的引用计数-1,直到最后使用 __ block变量的block被废弃的同时,堆上的 __ block也会被释放)。

_ NSConcreteMallocBlcok,该类的Block设置在堆上
先看一个简单的例子:

#import <stdio.h> int main(int argc, const char * argv[]) { int i = 3; void (^blk)(void) = ^{ printf("Hello World,%d",i); }; blk(); return 0; }

现在 __ main _ block _ func _ 0在实现中使用了指向该变量的指针,所以达到了修改外部变量的作用。

Block的实现

首先我们使用Xcode创建一个Project,点击File-->New-->Project,选择macOS中Application的Command Line Tool,然后设置Project Name即可。你好发现这个工程值包含了一个main.m文件,然后我们做如下更改(更改后的代码如下):

static void __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("Hello Worldddd"); }

struct __Block_byref_i_0 { void *__isa; __Block_byref_i_0 *__forwarding; int __flags; int __size; int i; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_i_0 *i; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __ma攻城掠地消费送礼_石狮批发女装市场在哪里in_block_func_0(struct __main_block_impl_0 *__cself) { __Block_byref_i_0 *i = __cself->i; // bound by ref (i->__forwarding->i) = (i->__forwarding->i) + 3; printf("Hello World,%d",(i->__forwarding->i)); } static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->i, (void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);} static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->i, 8/*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 = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main(int argc, const char * argv[]) { __attribute__((__blocks__(byref))) __Block_byref_i_0 i = {(void*)0,(__Block_byref_i_0 *)&i, 0, sizeof(__Block_byref_i_0), 3}; void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_i_0 *)&i, 570425344)); ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; }

impl.isa = &_NSConcreteStackBLock; impl.Flags = 0; impl.FuncPtr = __main_block_func_0; Desc = &__main_block_desc_0_DATA;

struct __main_block_impl_0 *__cself

转换成了:

预留位为0,大小为传入结构体的大小。接下来就是很重要的构造函数了:

^{printf("Hello Worldddd")};

另外Block其实实质上也是OC的对象。

使用clang编译后是这样的:

blk();

static struct __main_block_desc_0 { size_t reserved; size_t Block_size; } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

变换后的源代码如下:

你会发现它其实是一个结构体,该结构体的声明如下:

打印出来的结果相当于调用了blk输出的结果。接下来我们在item中跳转到main.m所在文件夹然后执行如下命令:

理解了上面刚才说的复制之后,现在回过来思考另一个问题: __ block的时候转换的结构体中的 __ forwarding指针有什么作用呢?(下面代码中的 __ forwarding)

以上便是对block的进一步介绍,主要参考了《Objective-C高级编程 iOS与OS X多线程和内存管理》一书。

struct __main_block_impl_0 tmpeImpl = __main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA) struct __main_block_impl_0 *blk = &tmpeImpl;

这个结构体就比较简单了,一个预留位,一个是指代该Block大小的属性,后面又包含了一个该实例:

热门文章
最新文章
Copyright © 2011-2018 超变态网页游戏 版权所有