为OC添加 Swift Defer 实现

94 阅读2分钟

实现代码:

static void blockCleanUp(void(^*block)(void)) {
    (*block)();
}
//为了添加@标识
#if DEBUG
#define DEFER_KEYWORD autoreleasepool {}
#else
#define DEFER_KEYWORD try {} @catch (...) {}
#endif
//为了使用__COUNTER__  内置变量
#define DEFER_IMPL(C, S) void(^__NSX_PASTE__(__EXT_DEFER_STMT_, C))(void) __attribute__((cleanup(blockCleanUp), unused)) = ^S
#define defer(statments) \
DEFER_KEYWORD \
DEFER_IMPL(__COUNTER__, statments)

使用方式:

[task lock];
@defer({
    [task unlock];
});

在成对出现的代码上使用,防止到最后忘记配对。如锁等。

实现思路:

  1. 利用GCC Variable Attributes 中的 cleanup,实现离开时调用
  2. 利用__NSX_PASTE__实现对变量名的组装
  3. 利用__COUNTER__对组装的变量名进行变化
  4. 利用autoreleasepool和try catch添加@标识

拓展知识:

  • Variable Attributes是什么?

它是GCC提供的编译器特性,让我们在声明变量时附加特定的信息。这些特定的信息用于指示编译器如何处理这些变量。 GCC Variable Attributes URL

  • cleanup是什么作用?

cleanup 支持传入无返回值、只带一个参数且类型要与变量的类型兼容的函数。 被 cleanup标记的变量,会在离开作用域时,将自身的引用作为参数传入cleanup的函数中,并调用此函数进行清理操作。

void cleanupBlock(int *a) {
  printf("%d",*a);
}
int value = __attribute__((cleanup(cleanupBlock))) = 2;
  • OC常用内置宏
 __VA_ATGS__

      可变参数宏中专用,表示所有传入的可变参数。

 __COUNTER__

      一个累加计数宏,常用来构造唯一变量名。

 __LINE__

      记录 LOG 信息时,常用的一个内置宏,预编译时会将其替换为当前的行号。

 __FILE__

      记录 LOG 信息时,常用的一个内置宏,预编译时会将其替换为当前文件的全路径。

__FILE_NAME__

      记录 LOG 信息时,常用的一个内置宏,预编译时会将其替换为当前的文件名。

 __DATE__

      记录 LOG 信息时,常用的一个内置宏,预编译时会将其替换为当前日期。

 __TIME__

      记录 LOG 信息时,常用的一个内置宏,预编译时会将其替换为当前时间。