defer如何在swift中使用?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
目前創(chuàng)新互聯(lián)公司已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站運(yùn)營、企業(yè)網(wǎng)站設(shè)計(jì)、懷化網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。一個(gè)代碼塊允許多個(gè)defer,多個(gè)defer執(zhí)行的順序從后到前\color{red}{從后到前}從后到前
測試案例1
func testDefer() { defer { print("方法中defer內(nèi)容") } if true { defer { print("if 中defer內(nèi)容") } print("if中最后的代碼") } print("方法中的代碼") if true { return } print("方法結(jié)束前最后一句代碼") } testDefer()
以上代碼打印結(jié)果:
if中最后的代碼
if 中defer內(nèi)容
方法中的代碼
方法中defer內(nèi)容
打印結(jié)果中,第一個(gè)if中的代碼及里面的defer最先執(zhí)行,方法中的defer最后執(zhí)行,由此可以看出,代碼塊中其他能夠執(zhí)行的代碼先執(zhí)行,最后執(zhí)行defer的內(nèi)容;defer的作用范圍不能簡單的看成方法,而是代碼塊(可能有些同學(xué)會(huì)有這樣的誤區(qū))
測試案例2
func testDefer() { print("開始") defer { print("defer 1 中的內(nèi)容") } defer { print("defer 2 中的內(nèi)容") } if true { return } defer { print("defer 3 中的內(nèi)容") } print("方法結(jié)束前最后一句代碼") } testDefer()
打印結(jié)果
開始
defer 2 中的內(nèi)容
defer 1 中的內(nèi)容
我們可以看到最后一個(gè)defer沒有執(zhí)行,所以defer定義的位置很重要,如果沒有執(zhí)行defer定義的代碼,在代碼塊結(jié)束前不會(huì)執(zhí)行defer中的內(nèi)容
多個(gè)defer的執(zhí)行順序從后到前
場景1:一些資源用完后需釋放,這里給的是官方的一個(gè)案例
func processFile(filename: String) throws { if exists(filename) { let file = open(filename) defer { close(file) } while let line = try file.readline() { // 處理文件。 } // close(file) 會(huì)在這里被調(diào)用,即作用域的最后。 } }
開始用到資源的時(shí)候就使用defer去釋放,避免忘記釋放資源
場景2:加鎖解鎖,借鑒了kingfisher
let lock = NSLock() func testDefer() { lock.lock() defer { lock.unlock() } doSomething() } testDefer()
在加鎖后立刻用defer解鎖,避免忘記解鎖
場景3:處理一些代碼塊作用域結(jié)束前的重復(fù)操作,比如請求網(wǎng)絡(luò)數(shù)據(jù)的時(shí)候
通常的一種寫法
func loadCityList(_ finish: ((Error?, [String]?) -> ())?) { DispatchQueue.global().async { // 模擬網(wǎng)絡(luò)請求 let data: AnyObject? // 模擬服務(wù)器返回的數(shù)據(jù) guard let dict = data as? [String: AnyObject] else { DispatchQueue.main.async { finish?(error, nil) } return } guard let code = dict["code"] as? Int, code == 200 else { DispatchQueue.main.async { finish?(error, nil) } return } guard let citys = dict["data"] as? [String]? else { DispatchQueue.main.async { finish?(error, nil) } return } DispatchQueue.main.async { finish?(nil, citys) } } }
當(dāng)每次有錯(cuò)誤處理時(shí)和結(jié)果正確時(shí)都需要去做回調(diào),而且回調(diào)可能有一堆代碼,看起來代碼會(huì)比較冗余,而且在一些錯(cuò)誤處理時(shí)很容易造成忘記回調(diào)
defer怎么去寫呢
func loadCityList(_ finish: ((Error?, [String]?) -> ())?) { DispatchQueue.global().async { // 模擬網(wǎng)絡(luò)請求 var error: Error? = nil var citys: [String]? = nil defer { DispatchQueue.main.async { finish?(error, citys) } } let data: AnyObject? // 模擬服務(wù)器返回的數(shù)據(jù) guard let dict = data as? [String: AnyObject] else { error = ... return } guard let code = dict["code"] as? Int, code == 200 else { error = ... return } guard let tempCitys = dict["data"] as? [String]? else { error = ... return } citys = tempCitys } }
使用defer既解決了代碼冗余,又解決了可能忘記回調(diào)的問題,還有當(dāng)我們看到defer時(shí),我們很清楚知道,無論網(wǎng)絡(luò)請求結(jié)果如果,都會(huì)回調(diào)
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,的支持。