×

如何扩展 Objective-C 语言

消耗积分:2 | 格式:rar | 大小:0.3 MB | 2017-09-26

分享资料个

  Variable Attributes 其实是 GCC 中用于描述变量的一种修饰符。我们可以使用 __attribute__ 来修饰一些变量来参与静态分析等编译过程;而在 Cocoa Touch 中很多的宏其实都是通过 __attribute__ 来实现的,例如:

  #define NS_ROOT_CLASS __attribute__((objc_root_class))

  而 cleanup 就是在这里会使用的变量属性:

  The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.

  GCC 文档中对 cleanup 属性的介绍告诉我们,在 cleanup 中必须传入 只有一个参数的函数并且这个参数需要与变量的类型兼容。

  如果上面这句比较绕口的话很难理解,可以通过一个简单的例子理解其使用方法:

  void cleanup_block(int *a) {

  printf(“%d\n”, *a);

  }

  int variable __attribute__((cleanup(cleanup_block))) = 2;

  在 variable 这个变量离开作用域之后,就会自动将这个变量的指针传入 cleanup_block 中,调用 cleanup_block 方法来进行『清理』工作。

  实现 defer

  到目前为止已经有了实现 defer 需要的全部知识,我们可以开始分析 libextobjc 是怎么做的。

  在 libextobjc 中并没有使用 defer 这个名字,而是使用了 onExit(表示代码是在退出作用域时执行)

  为了使 onExit 在使用时更加明显,libextobjc 通过一些其它的手段使得我们在每次使用 onExit 时都需要添加一个 @ 符号。

  {

  @onExit {

  NSLog(“Log when out of scope.”);

  };

  NSLog(“Log before out of scope.”);

  }

  onExit 其实只是一个精心设计的宏:

  #define onExit \

  ext_keywordify \

  __strong ext_cleanupBlock_t metamacro_concat(ext_exitBlock_, __LINE__) __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^

  既然它只是一个宏,那么上面的代码其实是可以展开的:

  autoreleasepool {}

  __strong ext_cleanupBlock_t ext_exitBlock_19 __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^ {

  NSLog(“Log when out of scope.”);

  };

  这里,我们分几个部分来分析上面的代码片段是如何实现 defer 的功能的:

  1. ext_keywordify 也是一个宏定义,它通过添加在宏之前添加 autoreleasepool {} 强迫 onExit 前必须加上 @ 符号。

  #define ext_keywordify autoreleasepool {}

  2. ext_cleanupBlock_t 是一个类型:

  typedef void (^ext_cleanupBlock_t)();

  3. metamacro_concat(ext_exitBlock_, __LINE__) 会将 ext_exitBlock 和当前行号拼接成一个临时的的变量名,例如:ext_exitBlock_19。

  4. __attribute__((cleanup(ext_executeCleanupBlock), unused)) 将 cleanup 函数设置为 ext_executeCleanupBlock;并将当前变量 ext_exitBlock_19 标记为 unused 来抑制 Unused variable 警告。

  5. 变量 ext_exitBlock_19 的值为 ^{ NSLog(“Log when out of scope.”); },是一个类型为 ext_cleanupBlock_t 的 block。

  6. 在这个变量离开作用域时,会把上面的 block 的指针传入 cleanup 函数,也就是 ext_executeCleanupBlock:

  void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block) {

  (*block)();

  }

  这个函数的作用只是简单的执行传入的 block,它满足了 GCC 文档中对 cleanup 函数的几个要求:

  只能包含一个参数

  参数的类型是一个指向变量类型的指针

  函数的返回值是 void

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !