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

跟建设通差不多额网站如何申请公众号

跟建设通差不多额网站,如何申请公众号,网站建设期末答案,行业网站建设分析Block 的实质究竟是什么呢#xff1f;类型#xff1f;变量#xff1f;还是什么黑科技#xff1f; Blocks 是 带有局部变量的匿名函数 Blocks 由 OC 转 C 源码方法 在项目中添加 blocks.m 文件#xff0c;并写好 block 的相关代码。打开「终端」#xff0c;执行 cd XX…Block  的实质究竟是什么呢类型变量还是什么黑科技  Blocks 是 带有局部变量的匿名函数 Blocks 由 OC 转 C 源码方法 在项目中添加 blocks.m 文件并写好 block 的相关代码。打开「终端」执行 cd XXX/XXX 命令其中 XXX/XXX 为 block.m 所在的目录。继续执行clang -rewrite-objc block.m执行完命令之后block.m 所在目录下就会生成一个 block.cpp 文件这就是我们需要的 block 相关的 C 源码。 1. /* 包含 Block 实际函数指针的结构体 */ 2. struct __block_impl { 3. void *isa; 4. int Flags;                5. int Reserved;        // 今后版本升级所需的区域大小 6. void *FuncPtr;      // 函数指针 7. }; 9. /* Block 结构体 */ 10. struct __main_block_impl_0 { 11. // implBlock 的实际函数指针指向包含 Block 主体部分的 __main_block_func_0 结构体 12.     struct __block_impl impl; 13.     // DescDesc 指针指向包含 Block 附加信息的 __main_block_desc_0 结构体 14.     struct __main_block_desc_0* Desc; 15.     // __main_block_impl_0Block 构造函数 16.     __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags0) { 17. impl.isa _NSConcreteStackBlock; 18.         impl.Flags flags; 19.         impl.FuncPtr fp; 20.         Desc desc; 21.     } 22. };23. /* Block 主体部分结构体 */ 24. static void __main_block_func_0(struct __main_block_impl_0 *__cself) { 25. printf(myBlock\n); 26. }27. /* Block 附加信息结构体包含今后版本升级所需区域大小Block 的大小*/ 28. static struct __main_block_desc_0 { 29. size_t reserved;        // 今后版本升级所需区域大小 30. size_t Block_size;    // Block 大小 31. } __main_block_desc_0_DATA { 0, sizeof(struct __main_block_impl_0)};32. /* main 函数 */ 33. int main () { 34.     void (*myBlock)(void) ((void (*)())__main_block_impl_0((void *)__main_block_func_0, __main_block_desc_0_DATA)); 35.     ((void (*)(__block_impl *))((__block_impl *)myBlock)-FuncPtr)((__block_impl *)myBlock);36.     return 0; 37. }Block 结构体 我们先来看看 __main_block_impl_0 结构体 Block 结构体 1. /* Block 结构体 */ 2. struct __main_block_impl_0 { 3.     // implBlock 的实际函数指针指向包含 Block 主体部分的 __main_block_func_0 结构体 4.     struct __block_impl impl; 5.     // DescDesc 指针指向包含 Block 附加信息的 __main_block_desc_0 结构体 6.     struct __main_block_desc_0* Desc; 7.     // __main_block_impl_0Block 构造函数 8. __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags0) { 9.         impl.isa _NSConcreteStackBlock; 10.         impl.Flags flags; 11.         impl.FuncPtr fp; 12.         Desc desc; 13.     } 14. };从上边我们可以看出__main_block_impl_0 结构体Block 结构体包含了三个部分 从上述代码可以看出block的本质是个 __main_block_impl_0 的结构体对象这就是为什么能用 % 打印出block的原因了 成员变量 impl;成员变量 Desc 指针;__main_block_impl_0 构造函数。析构函数中所需要的函数fp传递了具体的block实现__main_block_func_0然后保存在block结构体的impl中 block捕获变量 这就说明了block声明只是将block实现保存起来具体的函数实现需要自行调用 值得注意的是当block为堆block时block的构造函数会多出来一个参数a并且在block结构体中多出一个属性a 接着把目光转向__main_block_func_0实现 __cself是__main_block_impl_0的指针即block本身int a __cself-a即int a block-a由于a只是个属性所以是堆block只是值拷贝值相同内存地址不同这也是为什么捕获的外界变量不能直接进行操作的原因如a会报错 当__block修饰外界变量的时候 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q6SlRlhS-1690945388106)(https://raw.githubusercontent.com/ArnoVD97/PhotoBed/master/photo202307281627162.png)] __block修饰的属性在底层会生成响应的结构体保存原始变量的指针并传递一个指针地址给block——因此是指针拷贝 源码中增加了一个名为_Block_byref_a_0的结构体用来保存我们要capture并且修改的变量i __main_block_impl_0引用的是_Block_byref_a_0结构体指针起到修改外部变量的作用 _ Block_byref_a_0里面有isa也是一个对象 我们需要负责_Block_byref_a_0结构体相关的内存管理所以_main_block_desc_0中增加了copy和dispose的函数指针用于在抵用前后修改相应变量的引用计数 struct __block_impl impl 说明 第一部分 impl 是 __block_impl 结构体类型的成员变量。__block_impl 包含了 Block 实际函数指针 FuncPtrFuncPtr 指针指向 Block 的主体部分也就是 Block 对应 OC 代码中的 ^{ printf(myBlock\n); }; 部分。还包含了标志位 Flags今后版本升级所需的区域大小  Reserved__block_impl 结构体的实例指针 isa。 1. /* 包含 Block 实际函数指针的结构体 */ 2. struct __block_impl { 3. void *isa;               // 用于保存 Block 结构体的实例指针 4.   int Flags;               // 标志位 5.   int Reserved;        // 今后版本升级所需的区域大小 6.   void *FuncPtr;      // 函数指针 7. };struct __main_block_desc_0* Desc 说明 第二部分 Desc 是指向的是 __main_block_desc_0 类型的结构体的指针型成员变量__main_block_desc_0 结构体用来描述该 Block 的相关附加信息 今后版本升级所需区域大小 reserved 变量。Block 大小Block_size 变量。 1. /* Block 附加信息结构体包含今后版本升级所需区域大小Block 的大小*/ 2. static struct __main_block_desc_0 { 3. size_t reserved;      // 今后版本升级所需区域大小 4. size_t Block_size;  // Block 大小 5. } __main_block_desc_0_DATA { 0, sizeof(struct __main_block_impl_0)};__main_block_impl_0 构造函数说明 第三部分是 __main_block_impl_0 结构体Block 结构体 的构造函数负责初始化 __main_block_impl_0 结构体Block 结构体 的成员变量。 1. __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags0) { 2. impl.isa _NSConcreteStackBlock; 3.     impl.Flags flags; 4.     impl.FuncPtr fp; 5.     Desc desc; 6. }关于结构体构造函数中对各个成员变量的赋值我们需要先来看看 main() 函数中对该构造函数的调用。 void (*myBlock)(void) ((void (*)())__main_block_impl_0((void *)__main_block_func_0, __main_block_desc_0_DATA));我们可以把上面的代码稍微转换一下去掉不同类型之间的转换使之简洁一点 1. struct __main_block_impl_0 temp  __main_block_impl_0(__main_block_func_0, __main_block_desc_0_DATA); 2. struct __main_block_impl_0 myBlock temp;这样就容易看懂了。该代码将通过 __main_block_impl_0 构造函数生成的 __main_block_impl_0 结构体Block 结构体类型实例的指针赋值给 __main_block_impl_0 结构体Block 结构体类型的指针变量 myBlock。 可以看到 调用 __main_block_impl_0 构造函数的时候传入了两个参数。 第一个参数__main_block_func_0。     - 其实就是 Block 对应的主体部分可以看到下面关于 __main_block_func_0 结构体的定义 和 OC 代码中 ^{ printf(myBlock\n); }; 部分具有相同的表达式。     - 这里参数中的 __cself 是指向 Block 的值的指针变量相当于 OC 中的 self。 c /* Block 主体部分结构体 */ static void __main_block_func_0(struct __main_block_impl_0 *__cself) {      printf(myBlock\n); } 第二个参数__main_block_desc_0_DATA__main_block_desc_0_DATA 包含该 Block 的相关信息。 我们再来结合之前的 __main_block_impl_0 结构体定义。 - __main_block_impl_0 结构体Block 结构体可以表述为 1. struct __main_block_impl_0 { 2.      void *isa;               // 用于保存 Block 结构体的实例指针 3.     int Flags;               // 标志位 4.     int Reserved;        // 今后版本升级所需的区域大小 5.     void *FuncPtr;      // 函数指针 6.     struct __main_block_desc_0* Desc;      // DescDesc 指针 7. };- __main_block_impl_0 构造函数可以表述为 1. impl.isa _NSConcreteStackBlock;    // isa 保存 Block 结构体实例 2. impl.Flags 0;        // 标志位赋值 3. impl.FuncPtr  __main_block_func_0;    // FuncPtr 保存 Block 结构体的主体部分 4. Desc __main_block_desc_0_DATA;    // Desc 保存 Block 结构体的附加信息[[Block签名]] __main_block_impl_0 结构体Block 结构体相当于 Objective-C 类对象的结构体isa 指针保存的是所属类的结构体的实例的指针。_NSConcreteStackBlock 相当于 Block 的结构体实例。对象 impl.isa _NSConcreteStackBlock; 语句中将 Block 结构体的指针赋值给其成员变量 isa相当于 Block 结构体的成员变量 保存了 Block 结构体的指针这里和 Objective-C 中的对象处理方式是一致的。 也就是说明 Block 的实质就是对象。 block的copy分析 接下来就来研究下栈block转换成到堆block的过程——_Block_copy void *_Block_copy(const void *arg) {struct Block_layout *aBlock;if (!arg) return NULL;// The following would be better done as a switch statementaBlock (struct Block_layout *)arg;if (aBlock-flags BLOCK_NEEDS_FREE) {// latches on highlatching_incr_int(aBlock-flags);return aBlock;}else if (aBlock-flags BLOCK_IS_GLOBAL) {return aBlock;}else {// Its a stack block. Make a copy.struct Block_layout *result (struct Block_layout *)malloc(aBlock-descriptor-size);if (!result) return NULL;memmove(result, aBlock, aBlock-descriptor-size); // bitcopy first #if __has_feature(ptrauth_calls)// Resign the invoke pointer as it uses address authentication.result-invoke aBlock-invoke; #endif// reset refcountresult-flags ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not neededresult-flags | BLOCK_NEEDS_FREE | 2; // logical refcount 1_Block_call_copy_helper(result, aBlock);// Set isa last so memory analysis tools see a fully-initialized object.result-isa _NSConcreteMallocBlock;return result;} }整段代码主要分成三个逻辑分支 通过flags标识位——存储引用计数的值是否有效 block的引用计数不受runtime处理的是由自己管理的 static int32_t latching_incr_int(volatile int32_t *where) {while (1) {int32_t old_value *where;if ((old_value BLOCK_REFCOUNT_MASK) BLOCK_REFCOUNT_MASK) {return BLOCK_REFCOUNT_MASK;}if (OSAtomicCompareAndSwapInt(old_value, old_value2, where)) {return old_value2;}} }这里可能有个疑问 为什么引用计数是 2 而不是 1  因为flags的第一号位置已经存储着释放标记 else if (aBlock-flags BLOCK_IS_GLOBAL) {return aBlock; } 是否是全局block—— else {// Its a stack block. Make a copy.size_t size Block_size(aBlock);struct Block_layout *result (struct Block_layout *)malloc(size);// 开辟堆空间if (!result) return NULL;memmove(result, aBlock, size); // bitcopy first #if __has_feature(ptrauth_calls)// Resign the invoke pointer as it uses address authentication.result-invoke aBlock-invoke;#if __has_feature(ptrauth_signed_block_descriptors)if (aBlock-flags BLOCK_SMALL_DESCRIPTOR) {uintptr_t oldDesc ptrauth_blend_discriminator(aBlock-descriptor,_Block_descriptor_ptrauth_discriminator);uintptr_t newDesc ptrauth_blend_discriminator(result-descriptor,_Block_descriptor_ptrauth_discriminator);result-descriptor ptrauth_auth_and_resign(aBlock-descriptor,ptrauth_key_asda, oldDesc,ptrauth_key_asda, newDesc);} #endif #endif// reset refcountresult-flags ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not neededresult-flags | BLOCK_NEEDS_FREE | 2; // logical refcount 1_Block_call_copy_helper(result, aBlock);// Set isa last so memory analysis tools see a fully-initialized object.result-isa _NSConcreteMallocBlock;return result; } 栈block - 堆block的过程 先通过malloc在堆区开辟一片空间再通过memmove将数据从栈区拷贝到堆区invoke、flags同时进行修改block的isa标记成_NSConcreteMallocBlock [[__block的深入研究]]
http://www.dnsts.com.cn/news/81878.html

相关文章:

  • 购物型网站建设网站留言发送到邮箱
  • 福州整站优化360网站建设价位
  • 二级网站都在一台服务器怎么做域名798艺术区
  • 飞色网站商城怎么做万网域名备案查询
  • 山东公司网站建设大连建设工程信息网官网查询
  • 杭州建设企业网站的品牌建设网站
  • 电商网站 支付帮别人做数学题赚钱的网站
  • 网站的外链是怎么做的青岛做网站的 上市公司
  • 企业建站公司案例深信服网络架构
  • 重庆网站建设的培训机构电商有多少种方法推广
  • 好的网站设计培训机构长春网站建设首选网诚传媒_
  • 访问网站需要账号密码网站开发工具有
  • 知春路网站建设公司WordPress对象储存
  • 简述营销导向的企业网站建设的步骤企业邮箱申请哪个
  • 在线网站建设平台哪个好免费的网站建设有哪些
  • 网站开通wordpress 上传中文文件
  • 北京网站建设成都拖曳式网站建设
  • 排名前十网站建设wordpress导航图片
  • 公司网站建设是哪个部门的事情企业邮箱入口163
  • 网站后台图片编辑器伊犁北京网站建设
  • 域名进行网站备案什么系统有wordpress
  • 建什么类型网站好搜素引擎优化
  • 专业网站建站费用延庆县专业网站制作网站建设
  • 做网站反复修改青岛网络服务公司
  • 网站企业建设方案长沙网站制作案例
  • 重庆建设工程证照查询网站wordpress 4.6
  • 上海网站的优化宁波网络公司哪家最好
  • 行业数据网站wordpress 建点
  • 德兴网站建设公司百度推广 个人网站
  • 溧阳市建设工程质量监督站网站中文网站后台