onExit的用法是这样的:
- (void)exitTest {
@onExit {
NSLog(@"1");
};
{
@onExit {
NSLog(@"2");
};
{
@onExit {
NSLog(@"3");
};
}
}
@onExit {
NSLog(@"4");
};
}
就是和Swift的defer用法一样,在离开作用域的时候执行大括号里的代码。注意,同一个作用域下,后定义的@onExit先执行。
具体的定义如下:
#define onExit \
rac_keywordify \
__strong rac_cleanupBlock_t metamacro_concat(rac_exitBlock_, __LINE__) __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^
整体的宏结构和我们熟悉的@weakify,@strongify是一致的。
对于
@onExit {
NSLog(@"1");
};
宏展开之后就是:
__strong rac_cleanupBlock_t rac_exitBlock_xxxx __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^ {
NSLog(@"1");
};
其中rac_exitBlock_xxxx中的xxxx部分是当前的行号。
这句话的意思就是定义了一个叫rac_exitBlock_xxxx的变量,它是一个block,block的内容就是我们写的代码块了。
这里的关键是一个Clang编译器的修饰符attribute((cleanup(function)))。这个修饰符的作用是:被修饰变量在离开作用域的时候,执行其中指定的function,执行function的时候会把被修饰的变量的指针作为function的参数传递过去。
这样解析可能还是懵懵懂懂的。
看看具体的细节吧
typedef void (^rac_cleanupBlock_t)();
static inline void rac_executeCleanupBlock (__strong rac_cleanupBlock_t *block) {
(*block)();
}
ReactiveCocoa使用attribute((cleanup(function)))这个修饰符的时候,给的function是rac_executeCleanupBlock,这个function的就是执行传进来的这个block。
( ⊙ o ⊙ )啊!传进来的这个block不就正式我们写的代码块了嘛!
于是,这个特性的作用就是:在作用域结束的时候调用我们的代码块!