当前位置: 首页 > news >正文

镇江网站建设多少钱正规推广赚佣金的平台

镇江网站建设多少钱,正规推广赚佣金的平台,杭州网站开发wguser,网站建设可上传视频的block 文章目录block如何通过终端clang生成源码cpp文件block实质截获自动变量全局变量和静态变量的截获__block说明符iOS开发“强弱共舞”——weak和strong配套使用解决block循环引用问题如何通过终端clang生成源码cpp文件 之前在学习block中学习的比较浅,只看了oc…

block

文章目录

  • block
    • 如何通过终端clang生成源码cpp文件
    • block实质
    • 截获自动变量
    • 全局变量和静态变量的截获
    • __block说明符
    • iOS开发“强弱共舞”——weak和strong配套使用解决block循环引用问题

如何通过终端clang生成源码cpp文件

之前在学习block中学习的比较浅,只看了oc高级编程书上有的源码,学习的比较浅,这节来对之前的作以补充。
首先来看看怎么将oc文件生成cpp的源码文件:
在这里插入图片描述

将项目大文件里的二级文件,打开终端 cd 并将此文件拖入:
然后再输入:

clang -rewrite-objc main.m

在这里插入图片描述

回车打开之前的项目文件,即可看到生成了一个cpp文件,打开就是oc的c++源码。
打开后发现有60000多行,很抽象,关键部分看最前面和最后面即可。

block实质

我们现在时文件中写一个最简单的block,看看源码是什么:

int main(int argc, const char * argv[]) {@autoreleasepool {// insert code here...void (^blk)(void) = ^{printf("Block\n");};blk();}return 0;
}

源码:

//经过clang转换后的C++代码
struct __block_impl {void *isa;//指向所属类的指针int Flags;//标志性参数,暂时没用到所以默认为0int Reserved;//今后版本升级所需的区域大小。void *FuncPtr;//函数指针,指向实际执行的函数,也就是block中花括号里面的代码内容。
};struct __main_block_impl_0 {struct __block_impl impl;//上面点1中的结构体的变量struct __main_block_desc_0* Desc;//上面点2中的结构体的指针 __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};static void __main_block_func_0(struct __main_block_impl_0 *__cself {printf("Block\n");
}static struct __main_block_desc_0 {size_t reserved;  //今后版本升级所需区域的大小(一般填0)size_t Block_size;   //Block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};int main(int argc, const char * argv[]) {void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);return 0;
}

我们来分开说一下每部分的意义:
1.第一个结构体

struct __block_impl {void *isa;//指向所属类的指针int Flags;//标志性参数,暂时没用到所以默认为0int Reserved;//今后版本升级所需的区域大小。void *FuncPtr;//函数指针,指向实际执行的函数,也就是block中花括号里面的代码内容。
};
  • 结构体的名称:impl即implementation的缩写,换句话说这一部分是block的实现部分结构体。
  • void *isa:声明一个不确定类型的指针,用于保存Block结构体实例。
  • int Flags:标识符。
  • int Reserved:今后版本升级所需的区域大小。
  • void *FuncPtr:函数指针,指向实际执行的函数,也就是block中花括号里面的代码内容。

2.在介绍struct __main_block_impl_0结构体之前,先介绍一下这个结构体里的static struct __main_block_desc_0结构体
这个结构体在上面一坨源码的最底下:

static struct __main_block_desc_0 {size_t reserved;  //今后版本升级所需区域的大小(一般填0)size_t Block_size;   //Block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
  • 第一个成员变量指的是今后版本升级所需区域的大小(一般填0)。
  • 第二个成员变量是Block的大小。
    __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};:
    1⃣️.这就是和我们平时用结构体一样,在定义完最后写一个结构体实例变量,变量名就是__main_block_desc_0_DATA。
    2⃣️.其中reserved为0,Block_size是sizeof(struct __main_block_impl_0)。

3.接下来看struct __main_block_impl_0结构体

struct __main_block_impl_0 {struct __block_impl impl;//上面点1中的结构体的变量struct __main_block_desc_0* Desc;//上面点2中的结构体的指针__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};
  • 第一个成员变量是impl,也就是上面点1中的结构体的变量。
  • 第二个成员变量是Desc指针,就是上面点2中的结构体的指针。
  • 剩下的代码是:初始化含有这些结构体的__main_block_impl_0结构体的构造函数,给结构体里的元素赋值。

4.然后是static void __main_block_func_0

static void __main_block_func_0(struct __main_block_impl_0 *__cself {printf("Block\n");
}

这个就比较简单了,Blcok执行的实际代码块。也是点3中fp指针指向的函数。括号中的参数__cself是相当于OC语言版的self,代表的是Block本身。

5.最后来看main函数

int main(int argc, const char * argv[]) {void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);return 0;
}

这两句代码不长但是比较恶心,我们先来看第一句,把强制类型转换去一下试试:

//加了个临时变量temp,看着更方便点
struct __main_block_impl_0 temp = __main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
struct __main_block_impl_0 *blk = &temp;

该源代码将__main_block_impl_0结构体类型的自动变量,也就是栈上生成的__main_block_impl_0结构体实例的指针,赋值给__main_block_impl_0结构体指针类型的变量blk。
第二行代码就是相当于源代码中的blk(),即使用该Block部分。去掉转换部分就是:

(*blk->impl.FuncPtr)(blk);

这是使用函数指针调用函数。由Block语法转换的__main_block_impl_0函数的指针被赋值成员变量FunPtr中。

截获自动变量

int main(int argc, const char * argv[]) {int dmy = 256;int val = 10;const char  *fmt = "val = %d\n";void (^blk)(void) = ^{printf(fmt, val);};blk();return 0;
}

转化后的代码:

//经过clang转换后的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;const char *fmt;int val;__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, const char *_fmt, int _val, int flags=0) : fmt(_fmt), val(_val) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};static void __main_block_func_0(struct __main_block_impl_0 *__cself {const char *fmt = __cself->fmt;int val = __cself->val; printf(fmt, val);
}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)};int main(int argc, const char * argv[]) {int dmy = 256;int val = 10;const char *fmt = "val = %d\n";void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, fmt, val));return 0;
}

与上次不同的是在Block语法表达式中使用的自动变量被当作成员变量追加到了__main_block_impl_0结构体中:

struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;const char *fmt;int val;
}

初始化该结构体实例的构造函数也发生了变化

__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, const char *_fmt, int _val, int flags=0) : fmt(_fmt), val(_val) 

初始化时自动变量fmt和val进行了赋值操作:

	impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;fmt = "val = %d\n";val = 10;

在转换后的代码中,截获到__main_block_impl_0结构体实例的成员变量上的自动变量,这些变量在Block语法表达式之前被声明定义,所以之后即使改变自动变量的值也不会对Block语法中的内容有所变化。

总的来说,所谓“截获自动变量值”意味着在执行Block语法时,Block语法表达式所使用的自动变量值被保存到Block的结构体实例(即Block自身中)。
总结一下就是说:
调用__main_block_impl_0的构造函数,构造函数正常有两个参数,func_0和desc_0,在截获自动变量时,会把需要截获的自动变量也放入参数列表中,同时__main_block_impl_0中也会增加两个成员变量a,b,构造函数带参数就是自动给这两个成员变量赋值。在调用func_0时,直接通过__cself(相当于self,其传递的参数也是其本身)的a、b(此时的a,b就是成员变量中的,因为上面的构造函数已经赋值了)

全局变量和静态变量的截获

我们以以下代码为例:

int global_val = 10; // 全局变量
static int static_global_val = 20; // 静态全局变量int main(int argc, const char * argv[]) {@autoreleasepool {static int static_val = 30; // 静态局部变量void (^myLocalBlock)(void) = ^{global_val *= 1;static_global_val *= 2;static_val *= 3;printf("static_val = %d, static_global_val = %d, global_val = %d\n",static_val, static_global_val, global_val);};myLocalBlock();}return 0;
}

源码:

struct __block_impl {void *isa;int Flags;int Reserved;void *FuncPtr;
};int global_val = 10;
static int static_global_val = 20;struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;int *static_val;__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_val, int flags=0) : static_val(_static_val) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {int *static_val = __cself->static_val; // bound by copyglobal_val *= 1;static_global_val *= 2;(*static_val) *= 3;printf("static_val = %d, static_global_val = %d, global_val = %d\n",(*static_val), static_global_val, global_val);}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)};
int main(int argc, const char * argv[]) {/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; static int static_val = 30;void (*myLocalBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &static_val));((void (*)(__block_impl *))((__block_impl *)myLocalBlock)->FuncPtr)((__block_impl *)myLocalBlock);}return 0;
}

我们主要来看下这段代码:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {int *static_val = __cself->static_val; // bound by copyglobal_val *= 1;static_global_val *= 2;(*static_val) *= 3;printf("static_val = %d, static_global_val = %d, global_val = %d\n",(*static_val), static_global_val, global_val);}

我们发现只有static_val是从__cself中获取的值

再来看看上面的一段代码:

struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;int *static_val;__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_val, int flags=0) : static_val(_static_val) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};
  • 我们发现全局变量,静态全局变量,我们的Block都没有用结构体去特地保存它
  • 只有对于我们的静态局部变量会来保存,但这里要注意,我们使用的不是int static_val,而是int *static_val
  • 也就是说我们使用一个指针来保存的静态局部变量
  • 它会直接保存该变量的地址,之后的操作也是直接对该值本身进行操作,而不是向之前截获的那些变量,等于是重新开辟空间进行保存

产生这个问题的原因:
原因在于,我们的静态变量是存在数据区的,在程序结束前它其实一直都会存在,之所以会被称为局部,只是说出了作用域无法调用到它了,并不是说这块数据不存在了。因此我们只要自己准备好一个指针,保证出了作用域依然能调用到他就行;而对于自动变量,它们真正的问题在于一但出了作用域,直接被释放了,所以要在结构体里开辟空间重新存放,进行值传递
在这里插入图片描述

__block说明符

来看书上的例子:

int main(int argc, const char * argv[]) {__block int val = 10;void (^blk)(void) = ^{val = 1;printf("val = %d\n", val);};blk();return 0;
}

转换后的源码:

struct __Block_byref_val_0 {void *__isa;__Block_byref_val_0 *__forwarding;int __flags;int __size;int val;
};struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;__Block_byref_val_0 *val; // by ref__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val, int flags=0) : val(_val->__forwarding) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};static void __main_block_func_0(struct __main_block_impl_0 *__cself) {__Block_byref_val_0 *val = __cself->val; (val->__forwarding->val) = 1;printf("val = %d\n", (val->__forwarding->val));
}static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->val, (void*)src->val, BLOCK_FIELD_IS_BYREF);
}static void __main_block_dispose_0(struct __main_block_impl_0*src {_Block_object_dispose((void*)src->val, 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[]) {__Block_byref_val_0 val = {0,(__Block_byref_val_0 *)&val, 0, sizeof(__Block_byref_val_0), 10};blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);return 0;
}

和没加修饰符的比较来说,主要有两处不同:

struct __Block_byref_val_0 {void *__isa;__Block_byref_val_0 *__forwarding;int __flags;int __size;int val;
};

在第一个结构体中,我们发现多了一个__Block_byref_val_0 *__forwarding,这个相当于指向该结构体本身的一个指针。

第二个地方:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {__Block_byref_val_0 *val = __cself->val; (val->__forwarding->val) = 1;printf("val = %d\n", (val->__forwarding->val));
}

在这里我们发现打印的并不是__Block_byref_val_0 *val而是(val->__forwarding->val)。

最后来看一下主函数:

int main(int argc, const char * argv[]) {__Block_byref_val_0 val = {0,(__Block_byref_val_0 *)&val, 0, sizeof(__Block_byref_val_0), 10};blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);return 0;
}

看下其中赋值部分:

__Block_byref_val_0 val = {0,(__Block_byref_val_0 *)&val, 0, sizeof(__Block_byref_val_0), 10};

这个__block变量val变为了__Block_byref_val_0结构体变量。通过调用 static void __main_block_func_0函数(通过__Block_byref_val_0结构体成员变量__forwarding访问成员变量val),将10赋给val。

iOS开发“强弱共舞”——weak和strong配套使用解决block循环引用问题

__weak是为了解决循环引用

如果一个对象A持有了一个block,同时block内又持有了对象A,为了解决循环引用我们要在用__weak修饰完对象A后再去持有它,这样就解决了循环引用。

__strong可以防止block持有的对象提前释放

我们用GCD延迟方法打印self的信息:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{[self dismissViewControllerAnimated:YES completion:nil];__weak typeof(self) weakSelf = self;void (^Block) (void) = ^{dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{NSLog(@"%@", weakSelf);});};Block();
}

输出结果:

在这里插入图片描述
点击屏幕,当前控制器消失,同时被销毁掉,5秒后打印的weakSelf就是一个(null),而我们如果在block内使用__strong后就能保证再打印完strongSelf之后再释放当前控制器。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{[self dismissViewControllerAnimated:YES completion:nil];__weak typeof(self) weakSelf = self;void (^Block) (void) = ^{__strong typeof(self) strongSelf = weakSelf;dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{NSLog(@"%@", strongSelf);});};Block();
}

请添加图片描述


文章转载自:
http://dinncopeduncular.ydfr.cn
http://dinncohetmanate.ydfr.cn
http://dinncowhapper.ydfr.cn
http://dinncobarbel.ydfr.cn
http://dinncocobnut.ydfr.cn
http://dinncocourteously.ydfr.cn
http://dinncopress.ydfr.cn
http://dinncolangbeinite.ydfr.cn
http://dinncomoldiness.ydfr.cn
http://dinncooch.ydfr.cn
http://dinncoisle.ydfr.cn
http://dinncofaltering.ydfr.cn
http://dinncopyrography.ydfr.cn
http://dinncocanarian.ydfr.cn
http://dinncotomo.ydfr.cn
http://dinncosulphamethazine.ydfr.cn
http://dinncogalactosyl.ydfr.cn
http://dinncochiz.ydfr.cn
http://dinncohesped.ydfr.cn
http://dinncopeacenik.ydfr.cn
http://dinncojawbreaker.ydfr.cn
http://dinncomuscularity.ydfr.cn
http://dinnconomadize.ydfr.cn
http://dinncoupbraid.ydfr.cn
http://dinncoovertly.ydfr.cn
http://dinncomuscovite.ydfr.cn
http://dinncoferacity.ydfr.cn
http://dinncograven.ydfr.cn
http://dinncoconstitutional.ydfr.cn
http://dinncotoddy.ydfr.cn
http://dinncoviscoid.ydfr.cn
http://dinncocrossbred.ydfr.cn
http://dinncomeadowlark.ydfr.cn
http://dinncokincob.ydfr.cn
http://dinncohurray.ydfr.cn
http://dinncoreappear.ydfr.cn
http://dinncoadoze.ydfr.cn
http://dinncodulcite.ydfr.cn
http://dinncoamphimixis.ydfr.cn
http://dinncocitizeness.ydfr.cn
http://dinncomodeless.ydfr.cn
http://dinncoleukoderma.ydfr.cn
http://dinncoforlorn.ydfr.cn
http://dinncoagrimony.ydfr.cn
http://dinncocryopump.ydfr.cn
http://dinncoskyport.ydfr.cn
http://dinncoconstellation.ydfr.cn
http://dinncoscreenwash.ydfr.cn
http://dinncobestead.ydfr.cn
http://dinncoautogeneration.ydfr.cn
http://dinncomural.ydfr.cn
http://dinncounsubsidized.ydfr.cn
http://dinncoedifying.ydfr.cn
http://dinncogutturalization.ydfr.cn
http://dinncoequivalent.ydfr.cn
http://dinncoaby.ydfr.cn
http://dinncokaryolymph.ydfr.cn
http://dinncotoiler.ydfr.cn
http://dinncoiberis.ydfr.cn
http://dinncotransalpine.ydfr.cn
http://dinncosporangiospore.ydfr.cn
http://dinncotoshiba.ydfr.cn
http://dinncopolystyle.ydfr.cn
http://dinncoequites.ydfr.cn
http://dinncobarfly.ydfr.cn
http://dinncobarmaid.ydfr.cn
http://dinncopalynology.ydfr.cn
http://dinncoautogenesis.ydfr.cn
http://dinncoslipsole.ydfr.cn
http://dinncoorganomercurial.ydfr.cn
http://dinncobaleen.ydfr.cn
http://dinncoladle.ydfr.cn
http://dinncobrocoli.ydfr.cn
http://dinncoeliot.ydfr.cn
http://dinncoencyclopedist.ydfr.cn
http://dinncobombshell.ydfr.cn
http://dinncohypothalamic.ydfr.cn
http://dinncotranssexualist.ydfr.cn
http://dinncounhandily.ydfr.cn
http://dinncoinjudicious.ydfr.cn
http://dinncoshindy.ydfr.cn
http://dinncogrossularite.ydfr.cn
http://dinncocandlelighting.ydfr.cn
http://dinncostirp.ydfr.cn
http://dinncoconfidentiality.ydfr.cn
http://dinncohadj.ydfr.cn
http://dinncopotence.ydfr.cn
http://dinncoacoustic.ydfr.cn
http://dinncocpsc.ydfr.cn
http://dinncocontradistinction.ydfr.cn
http://dinncopotamology.ydfr.cn
http://dinncomazy.ydfr.cn
http://dinncoovercontain.ydfr.cn
http://dinncoeasier.ydfr.cn
http://dinncolighthearted.ydfr.cn
http://dinncosemiatheist.ydfr.cn
http://dinncouglily.ydfr.cn
http://dinncoinclosure.ydfr.cn
http://dinncocomputery.ydfr.cn
http://dinncotachinid.ydfr.cn
http://www.dinnco.com/news/140656.html

相关文章:

  • 棋牌室的网站怎么做企业网站的功能
  • 网站建设制作文献搜索引擎google
  • 百度免费做网站友情链接方面
  • 电子商务网站解决方案网站运营是做什么的
  • 做网站需要的资料新闻最新头条10条
  • 六安网站制作多少钱百度指数查询移动版
  • 个人站点的制作网页怎么搜索关键词
  • 庆阳市镇原县疫情最新情况惠州seo外包平台
  • 网站建设 经营范围百度站内搜索
  • 事业单位做网站需要前置审批吗如何查询百度收录
  • 土巴兔装修公司电话seo长尾关键词排名
  • 苏州建站模板搭建外链seo
  • 想开发一个网站需要怎样做广告推广文案
  • wordpress漂浮花瓣西安seo服务培训
  • 做网站的人 优帮云淘宝直通车推广怎么收费
  • 建设部网站简短的软文范例
  • 网站的建设和设计方案网站服务器查询工具
  • 直播网站开发核心技术站长工具综合查询系统
  • 建网站建设公司优秀企业网站欣赏
  • 电子商务网站建设实训日记优秀的网页设计网站
  • 做的网站里面显示乱码怎么解决方法今日油价92汽油价格
  • 适合大学生做兼职的网站有哪些北京刚刚宣布比疫情更可怕的事情
  • 成都免费建站模板网络营销策划方案案例
  • 36kr源码WordPress北京seo供应商
  • 枣庄网站设计南京seo排名优化公司
  • 天一建设网站seo收录查询工具
  • 如何入驻亚马逊跨境电商seo高级教程
  • 网站建设公司发展网销是什么工作好做吗
  • 英文 日文网站建设申请中国站长工具
  • 微信链接网页网站制作百度推广电话是多少