swift的defer语法(defer语句不会立马执行,而是被推入栈中,直到作用域结束时才执行),其所在作用域结束,defer语句自下而上(先入后出)执行。
如下将会在testForDefer()函数结束时,执行情况是:
A处返回:doSomethingA
B处返回:doSomethingB,doSomethingA
执行到最后:doSomethingC,doSomethingB,doSomethingA
func testForDefer() {
defer{doSomethingA}
if (conditionA) {
return;//A
}
defer{doSomethingB}
if (conditionB) {
return;//B
}
defer{doSomethingC}
}
Objective_C上也可达到同样的操作,GCC使用 __attribute__ 关键字来描述函数,变量和数据类型的属性,其中__attribute__((cleanup(clean_function))描述当一个变量的作用域消失时,便会执行后面的clean_function函数.
如下指针p在{}作用域结束后,会调用my_free函数并对定义的变量p指针进行操作--释放喽
static void my_free(void* p) {
void** pp = (void**) p;
free(*pp);
}
{
int *p __attribute__((cleanup(my_free))) = (int*) malloc(sizeof(int));
}
由上可见,可用 __attribute__修饰变量block,并在定义的clean_function函数中操作对应定义的block,即可实现简单并清晰的插入代码段并在作用域结束时调用执行
typedef void (^cleanupBlock_t)();
static void blockCleanUp(cleanupBlock_t *block) {
(*block)();
}
#define onExit\
__strong cleanupBlock_t block __attribute__((cleanup(blockCleanUp), unused)) = ^
使用如下
{
onExit {
doSomething
};
}
是不是觉得上面的就OK啦?哈哈,再仔细看会发现,作用域中不能同时使用onExit{},因为block重定义了,因此这里要将宏定义中的block名称改下,改成作用域中具有唯一性,这里使用了__COUNTER__计数器(也可以使用__LINE__),一般用来后缀在变量上面,保证变量的唯一性.在程序中,每使用一次,这个数字就+1,默认是0
#define __NSX_PASTE__BLOCK(x,L) __NSX_PASTE__(x,L)
#define onExit\
__strong cleanupBlock_t __NSX_PASTE__BLOCK(block_, __COUNTER__) __attribute__((cleanup(blockCleanUp), unused)) = ^
至此就完成Objective_C的成对出现的代码写在一起达到swift中defer的效果了!
若是项目中使用RAC,就可发现它已定义一个宏onExit来实现block的修饰及执行了(具体实现及使用可自行翻阅RAC中的onExit宏),它的实现更为完整跟周到,其中将clean_function函数声明为inline,避免了栈内存的消耗
网友评论