中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

defer如何在swift中使用

發布時間:2021-01-05 14:36:10 來源:億速云 閱讀:137 作者:Leah 欄目:開發技術

defer如何在swift中使用?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

defer語句在代碼塊(方法、閉包等,可以理解為大括號包裝起來的代碼)作用域退出之前\color{red}{作用域退出之前}作用域退出之前執行,也就是代碼塊中其他應該執行的代碼都執行完了,才執行defer中的代碼

一個代碼塊允許多個defer,多個defer執行的順序從后到前\color{red}{從后到前}從后到前

一些測試及誤區糾正

測試案例1

func testDefer() {
 defer {
 print("方法中defer內容")
 }
 if true {
 defer {
  print("if 中defer內容")
 }
 print("if中最后的代碼")
 }
 print("方法中的代碼")
 if true {
 return
 }
 print("方法結束前最后一句代碼")
}
testDefer()

以上代碼打印結果:

if中最后的代碼
if 中defer內容
方法中的代碼
方法中defer內容

打印結果中,第一個if中的代碼及里面的defer最先執行,方法中的defer最后執行,由此可以看出,代碼塊中其他能夠執行的代碼先執行,最后執行defer的內容;defer的作用范圍不能簡單的看成方法,而是代碼塊(可能有些同學會有這樣的誤區)

測試案例2

func testDefer() {
 print("開始")
 defer {
 print("defer 1 中的內容")
 }
 defer {
 print("defer 2 中的內容")
 }
 if true {
 return
 }
 defer {
 print("defer 3 中的內容")
 }
 print("方法結束前最后一句代碼")
}
testDefer()

打印結果

開始
defer 2 中的內容
defer 1 中的內容

我們可以看到最后一個defer沒有執行,所以defer定義的位置很重要,如果沒有執行defer定義的代碼,在代碼塊結束前不會執行defer中的內容

多個defer的執行順序從后到前

一些實際應用場景

場景1:一些資源用完后需釋放,這里給的是官方的一個案例

func processFile(filename: String) throws {
 if exists(filename) {
 let file = open(filename)
 defer {
  close(file)
 }
 while let line = try file.readline() {
  // 處理文件。
 }
 // close(file) 會在這里被調用,即作用域的最后。
 }
}

開始用到資源的時候就使用defer去釋放,避免忘記釋放資源

場景2:加鎖解鎖,借鑒了kingfisher

let lock = NSLock()
func testDefer() {
 lock.lock()
 defer {
 lock.unlock()
 }
 
 doSomething()
}
testDefer()

在加鎖后立刻用defer解鎖,避免忘記解鎖

場景3:處理一些代碼塊作用域結束前的重復操作,比如請求網絡數據的時候

通常的一種寫法

func loadCityList(_ finish: ((Error?, [String]?) -> ())?) {
 DispatchQueue.global().async { // 模擬網絡請求
 let data: AnyObject? // 模擬服務器返回的數據
 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)
 }
 }
}

當每次有錯誤處理時和結果正確時都需要去做回調,而且回調可能有一堆代碼,看起來代碼會比較冗余,而且在一些錯誤處理時很容易造成忘記回調

defer怎么去寫呢

func loadCityList(_ finish: ((Error?, [String]?) -> ())?) {
 DispatchQueue.global().async { // 模擬網絡請求
 var error: Error? = nil
 var citys: [String]? = nil
 defer {
  DispatchQueue.main.async {
  finish?(error, citys)
  }
 }
 
 let data: AnyObject? // 模擬服務器返回的數據
 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既解決了代碼冗余,又解決了可能忘記回調的問題,還有當我們看到defer時,我們很清楚知道,無論網絡請求結果如果,都會回調

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

敖汉旗| 松桃| 汶上县| 清远市| 阳春市| 汉阴县| 伊金霍洛旗| 建瓯市| 双鸭山市| 扎鲁特旗| 静安区| 长顺县| 都昌县| 博野县| 阆中市| 大田县| 白朗县| 石台县| 尼木县| 晋江市| 嘉禾县| 阿克陶县| 上栗县| 绵竹市| 额尔古纳市| 时尚| 酒泉市| 顺平县| 台南市| 景洪市| 区。| 咸阳市| 吉隆县| 库车县| 钦州市| 邵阳县| 永安市| 共和县| 通城县| 民权县| 曲周县|