实现代码:
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];
});
在成对出现的代码上使用,防止到最后忘记配对。如锁等。
实现思路:
- 利用GCC Variable Attributes 中的 cleanup,实现离开时调用
- 利用__NSX_PASTE__实现对变量名的组装
- 利用__COUNTER__对组装的变量名进行变化
- 利用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 信息时,常用的一个内置宏,预编译时会将其替换为当前时间。