defer
defer
是Swift中比較常用的一種語法庙洼,defer
中的代碼將會在當(dāng)前的代碼塊結(jié)束之后調(diào)用栏赴。正如文檔中所說:
You use a defer statement to execute a set of statements just before code execution leaves the current block of code. This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block of code—whether it leaves because an error was thrown or because of a statement such as return or break.
無論你的代碼塊是通過break退出還是return退出,你在defer中代碼都會得到執(zhí)行耿眉,簡單演示如下:
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
cleanup
OC中也有類似的概念边翼,那就是黑魔法之一 __attribute__(cleanup(...))
。
cleanup用來修飾一個變量鸣剪,當(dāng)他的作用域結(jié)束组底,一般來講就是當(dāng)前的代碼塊執(zhí)行結(jié)束的時候,可以執(zhí)行一個指定的方法西傀。當(dāng)然斤寇,這個變量也可以是一個block。
__unused static void cleanUpBlock(__strong void(^*block)(void)) {
(*block)();
}
- (void)cleanUp {
__strong void(^attribute_cleanup_block)(void) __attribute__((cleanup(cleanUpBlock), unused)) = ^{
NSLog(@"clean up");
};
NSLog(@"processing");
}
當(dāng)然我們也可以把上面的內(nèi)容變成一個宏方便我們使用:
#ifdef __GNUC__
__unused static void cleanUpBlock(__strong void(^*block)(void)) {
(*block)();
}
#define OnBlockExit __strong void(^attribute_cleanup_block)(void) __attribute__((cleanup(cleanUpBlock), unused)) = ^
#endif
- (void)cleanUp {
OnBlockExit{
NSLog(@"Clean up");
};
NSLog(@"processing");
}
復(fù)數(shù)場景
還有一點(diǎn)要說的就是 Swift中的defer是可以疊加的拥褂,也就是說我也以寫出如下的代碼:
func cleanup() {
defer {
print("defer 1")
}
defer {
print("defer 2")
}
defer {
print("defer 3")
}
print("End")
}
cleanup()
控制臺會依次輸出:
End
defer 3
defer 2
defer 1
OC中由于上面的宏定義的block名稱相同娘锁,所以簡單對宏做了一點(diǎn)改動,將block的名稱摘了出來:
#define OnBlockExit(block_name) __strong void(^block_name)(void) __attribute__((cleanup(cleanUpBlock), unused)) = ^
- (void)cleanUp {
OnBlockExit(block_1) {
NSLog(@"OnBlockExit 1");
};
OnBlockExit(block_2) {
NSLog(@"OnBlockExit 2");
};
OnBlockExit(block_3) {
NSLog(@"OnBlockExit 3");
};
NSLog(@"End");
}
//控制臺輸出:
End
OnBlockExit 3
OnBlockExit 2
OnBlockExit 1
可以看出無論是 defer還是cleanup饺鹃,再添加“死亡回調(diào)”的時候都是按照棧的結(jié)構(gòu)添加的莫秆。
應(yīng)用
defer常用與需要配對出現(xiàn)的代碼,比如文件的打開與關(guān)閉悔详,加鎖與解鎖镊屎,ARC以外的對象,如CoreGraphics中對象的create與release等茄螃。
由于代碼較少缝驳,且網(wǎng)上也可以搜到很多類似的資料,這次就不提供源碼了归苍,謝謝大家支持 : )