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不就正式我們寫的代碼塊了嘛!
于是,這個特性的作用就是:在作用域結束的時候調用我們的代碼塊!