珠海网站开发哪家好网站建设中英语如何说

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

珠海网站开发哪家好,网站建设中英语如何说,小程序制作用华网天下优惠,广州市网站建设制作1.block的使用 1.1什么是block#xff1f; Blocks是C语言的扩充功能#xff1a;带有自动变量#xff08;局部变量#xff09;的匿名函数。 “带有自动变量”在Blocks中表现为“截取自动变量 “匿名函数”就是“不带名称的函数” 块#xff0c;封装了函数调用及调用…1.block的使用 1.1什么是block Blocks是C语言的扩充功能带有自动变量局部变量的匿名函数。 “带有自动变量”在Blocks中表现为“截取自动变量 “匿名函数”就是“不带名称的函数” 块封装了函数调用及调用环境的OC对象 block的声明 // 1. property (nonatomic, copy) void(^myBlock1)(void); // 2.BlockType:类型别名 typedef void(^BlockType)(void); property (nonatomic, copy) BlockType myBlock2; // 3. // 返回值类型(^block变量名)(参数1类型,参数2类型,…) void(^block)(void);block的定义 // ^返回值类型(参数1,参数2,…){};// 1.无返回值无参数void(^block1)(void) ^{};// 2.无返回值有参数void(^block2)(int) ^(int a){};// 3.有返回值无参数不管有没有返回值定义的返回值类型都可以省略int(^block3)(void) ^int{return 3;};// 以上Block的定义也可以这样写int(^block4)(void) ^{return 3;};// 4.有返回值有参数int(^block5)(int) ^int(int a){return 3 * a;};block的调用 // 1.无返回值无参数block1();// 2.有返回值有参数int a block5(2)2.block的底层数据结构 通过Clang将以下的OC代码转化为C代码 // Clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m //main.m #import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {void(^block)(void) ^{NSLog(我是 block);};block();}return 0; }转化为C代码 //参数结构体 struct __main_block_impl_0 {struct __block_impl impl;// block 结构体struct main_block_desc_0* Desc;// block 的描述对象 /* block 的构造函数** 返回值main_block_impl_0 结构体** 参数一main_block_func_0 结构体** 参数二main_block_desc_0 结构体的地址** 参数三flags 标识位 */__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags0) {impl.isa _NSConcreteStackBlock;// _NSConcreteStackBlock 表示存储在栈上impl.Flags flags;impl.FuncPtr fp;Desc desc;} };//block 结构体 struct block_impl {void *isa;//block 的类型int Flags;int Reserved;void *FuncPtr;// block的执行函数指针指向main_block_func_0 };//封装了 block 中的代码 //参数是__main_block_impl_0结构体的指针 static void __main_block_func_0(struct main_block_impl_0 *cself) {NSLog((NSString *)NSConstantStringImplvar_folders_yx_7jg_wdg128v45l4cn_1g265h0000gn_T_main_03dcda_mi_0);}static struct __main_block_desc_0 {size_t reserved;size_t Block_size;// block 所占的内存空间 } __main_block_desc_0_DATA { 0, sizeof(struct __main_block_impl_0)};int main(int argc, const char * argv[]) {/* autoreleasepool / { __AtAutoreleasePool __autoreleasepool; /** void(^block)(void) ^{NSLog(调用了block);};** 定义block的本质** 调用__main_block_impl_0()构造函数** 并且给它传了两个参数 __main_block_func_0 和 __main_block_desc_0_DATA** __main_block_func_0 封装了block里的代码** 拿到函数的返回值再取返回值的地址 main_block_impl_0** 把这个地址赋值给 block*/void(block)(void) ((void ()())main_block_impl_0((void )__main_block_func_0, __main_block_desc_0_DATA)); /** block();** 调用block的本质** 通过 __main_block_impl_0 中的 block_impl 中的 FuncPtr 拿到函数地址直接调用/ ((void ()(block_impl *))((block_impl *)block)-FuncPtr)((block_impl *)block);}return 0; }3.block的变量捕获机制 对于全局变量不会捕获到block内部访问方为直接访问对于auto类型的局部变量会捕获到block内部block内部会自动生成一个成员变量访问方式为值传递对于static类型的局部变量会捕获到block内部block内部会自动生成一个成员变量访问方式为指针传递对于对象类型的局部变量block会连同修饰符一起捕获 3.1 auto自动变量 将以下 OC 代码转换为 C 代码并贴出部分变动代码 int main(int argc, const char * argv[]) {autoreleasepool {int age 10;void(^block)(void) ^{NSLog(%d,age);};block();}return 0; }struct __main_block_impl_0 {struct __block_impl impl;struct main_block_desc_0* Desc;int age;//生成的变量main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags0) : age(_age) {impl.isa _NSConcreteStackBlock;impl.Flags flags;impl.FuncPtr fp;Desc desc;} }; static void __main_block_func_0(struct main_block_impl_0 *cself) {int age cself-age; // bound by copyNSLog((NSString *)NSConstantStringImplvar_folders_yx_7jg_wdg128v45l4cn_1g265h0000gn_T_main_40c716_mi_0,age);}可以看出 在main_block_impl_0结构体中会自动生成一个相同类型的age变量构造函数__main_block_impl_0中多出了一个age参数用来捕获外部的变量 由于传递方式为值传递所以我们在block外部修饰age变量时不会影响到block中的age变量 总的来说所谓“截获自动变量”意味着在执行Block语法时Block语法表达式所用的自动变量被保存到Block的结构体实例中即Block自身中 3.2static类型的局部变量 将以下OC代码转化为C代码并贴出部分变动代码 static int age 10;void(^block)(void) ^{NSLog(%d,age);};age 20;block();// 20struct __main_block_impl_0 {struct __block_impl impl;struct main_block_desc_0* Desc;int *age;main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_age, int flags0) : age(_age) {impl.isa _NSConcreteStackBlock;impl.Flags flags;impl.FuncPtr fp;Desc desc;} }; static void __main_block_func_0(struct main_block_impl_0 *cself) {int *age cself-age; // bound by copyNSLog((NSString *)NSConstantStringImpl__var_folders_yx_7jg_wdg128v45l4cn_1g265h0000gn_T_main_cb7943_mi_0,(*age));}可以看出 main_block_impl_0结构体中生成了一个相同类型的age变量main_block_impl_0构造函数多了个参数用来捕获外部的age变量的地址 由于传递方式是指针传递所以修改局部变量age时age的值会随之变化 3.3全局变量 将以下OC代码转化为C代码并贴出部分变动代码 int height 10; static int age 20; int main(int argc, const char * argv[]) {autoreleasepool {void(^block)(void) ^{NSLog(%d,%d,height,age);};block();}return 0; }int height 10; static int age 20;struct __main_block_impl_0 {struct __block_impl impl;struct main_block_desc_0* Desc;main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags0) {impl.isa _NSConcreteStackBlock;impl.Flags flags;impl.FuncPtr fp;Desc desc;} }; static void __main_block_func_0(struct main_block_impl_0 *cself) {NSLog((NSString *)NSConstantStringImplvar_folders_yx_7jg_wdg128v45l4cn_1g265h0000gn_T_main_7a340f_mi_0,height,age);}可以看出 __main_block_impl_0结构体中并没有自动生成age和height全局变量也就是说没有将变量捕获到block内部 虽然block语法的匿名函数部分简单地变换为了C语言函数但从这个变换的函数中访问静态全局变量/全局变量并没有任何改变可直接使用。 但是静态变量的情况下转换后的函数原本就设置在含有Block语法的函数外所以无法从变量作用域访问 为什么局部变量需要捕获而全局变量不用呢 作用域的原因全局变量哪里都可以直接访问所以不用捕获局部变量外部不能直接访问所以需要捕获auto类型的局部变量可能会销毁其内存会消失block将来执行代码的时候不可能再去访问呢块内存所以捕获其值static变量会一直保存在内存中所以捕获其地址即可 3.4 _block修饰的变量 3.4.1 _block的使用 默认情况下block是不能修改外面的auto变量解决办法 变量用static修饰原因捕获static类型的局部变量是指针传递可以访问到该变量的内存地址全局变量_block我们只是希望临时用一下这个变量临时改一下而已而改为static变量和全局变量会一直在内存中 3.4.2 _block修饰符 _block同于解决block内部无法修改auto变量值的问题_block不能修饰全局变量静态变量编译器会将_block变量包装成一个对象struct __Block_byref_age_0byref按地址传递加_block修饰不会改变变量的性质他还是auto变量一般情况对捕获变量进行赋值赋值使用操作需要添加_block修饰符比如给数组添加或删除对象就不用加_bolck修饰符在 MRC 下使用 __block 修饰对象类型在 block 内部不会对该对象进行 retain 操作所以在 MRC 环境下可以通过 block 解决循环引用的问题 将以下 OC 代码转换为 C 代码并贴出部分变动代码 int main(int argc, const char * argv[]) {autoreleasepool {block int age 10;void(^block)(void) ^{age 20;NSLog(block-%d,age);};block();NSLog(%d,age);}return 0; }struct Block_byref_age_0 {void *isa; Block_byref_age_0 *forwarding;//持有指向该实例自身的指针int __flags;int __size;int age; };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 flags0) : 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) {__Block_byref_age_0 *age cself-age; // bound by ref(age-forwarding-age) 20;NSLog((NSString *)NSConstantStringImplvar_folders_yx_7jg_wdg128v45l4cn_1g265h0000gn_T_main_75529b_mi_0,(age-__forwarding-age));} static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0src) {_Block_object_assign((void)dst-age, (void*)src-age, 8/BLOCK_FIELD_IS_BYREF/);}static void __main_block_dispose_0(struct main_block_impl_0src) {_Block_object_dispose((void)src-age, 8/BLOCK_FIELD_IS_BYREF/);}可以看出 编译器会将_block修饰的变量包装成一个Block_byref_age_0结构体对象以上age 20 的赋值过程通过block的__main_block_func_0结构体实例中 __Block_byref_age_0类型的age指针找到 __Block_byref_age_0结构体的对象 Block_byref_age_0结构体对象持有指向实例本身的forwarding指针通过成员变量_forwarding访问 __Block_byref_age_0结构体里的age变量并将值改为20