Swift學習記錄 -- 14.閉包的使用和解決迴圈引用方法
阿新 • • 發佈:2019-01-29
Swift中的閉包 , 幾乎和OC中的block一模一樣 , 我個人又比較偏好block , 所以覺得閉包還是蠻不錯的 . 在迴圈引用問題上 , 解決方案也更加簡潔
// HttpTool類
import UIKit
class HttpTool: NSObject {
//閉包寫法 : (引數列表) -> (返回值型別)
func loadData(callBack:(jsonData:String) -> ()) {
//模擬網路請求 (因為我這裡使用的是xCode低版本 , 所以方法名稱具體有所不一樣,但是寫法都是差不多的)
dispatch_async(dispatch_get_global_queue(0 , 0)) {
print("傳送網路請求 -- \(NSThread.currentThread())")
//主執行緒更新UI
dispatch_async(dispatch_get_main_queue(), {
callBack(jsonData: "json資料")
})
}
}
//模擬網路請求二
//定義閉包型別屬性,儲存閉包回撥操作
var backOperation:((jsonData:String) -> ())? = nil
func loadMoreData(backOperation:(jsonData:String) ->() ) {
//儲存操作
self.backOperation = backOperation
//子執行緒請求
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("傳送網路請求:\(NSThread.currentThread())")
//主執行緒回撥更新UI
dispatch_async(dispatch_get_main_queue()) {
// backOperation(jsonData: "json資料")
self.backOperation?(jsonData:"json資料")
}
}
}
}
//未涉及迴圈引用情況 :
//建立HttpTool例項物件
let tool :HttpTool = HttpTool()
//呼叫模擬網路請求方法
tool.loadData { (jsonData) in
print("獲取資料\(jsonData),進行主執行緒更新UI")
print(NSThread.currentThread())
}
//注意:這種情況已經造成了迴圈引用
//閉包為self.tool屬性 , 故指標指向了閉包所在記憶體地址 . 在下述閉包中, 又訪問了self的記憶體地址進行背景色賦值 .
//解決辦法迴圈引用方法一: (和OC一致 ,弱化self)
weak var weakself = self
tool.loadMoreData { (jsonData) in
// weakself?的意思是:如果weakself沒有值 , 後面的程式碼將不會執行 , 如果weakself有值 , 那麼會自動將weakself進行解包,並執行後續程式碼
// 個人覺得這點的設計還是非常人性化的,不知道這個語法前,我就在想,如果一直需要進行if判斷,然後解包, 這程式碼也太爛了
weakself?.view.backgroundColor = UIColor.redColor()
print("獲取資料\(jsonData) --- 當前執行緒:\(NSThread.currentThread())")
}
//解決迴圈引用方法二 : (直接在大括號後,寫[weak self],推薦使用)
tool.loadMoreData {[weak self] (jsonData) in
//這裡的self依然變成可選型別
self?.view.backgroundColor = UIColor.greenColor()
print("獲取資料\(jsonData) --- 當前執行緒:\(NSThread.currentThread())")
}
//解決迴圈引用方法三: (不推薦 , 如果self為空, 直接崩潰)
tool.loadMoreData {[unowned self] (jsonData) in
self.view.backgroundColor = UIColor.greenColor()
print("獲取資料\(jsonData) --- 當前執行緒:\(NSThread.currentThread())")
}
}
//備註:
/* unowned 很類似於 OC中的__unsafe_unretained , 如果unowned修飾的弱引用,指標指向的物件銷燬 , 指標依然指向該記憶體地址 , 訪問殭屍物件,造成'野指標'錯誤
weak 就相當於OC中的 __weak ,如果weak修飾的弱引用 ,指標指向的物件銷燬, 指標會立即置為nil
*/
//控制器銷燬呼叫 , 相當於OC中的 dealloc
deinit {
print("---控制器銷燬")
}
————– 補充 : 尾隨閉包
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//尾隨閉包:如果閉包作為函式的最後一個引數,那麼閉包可以將()省略
//寫法1:
test ({ (str) in
print("\(str),world !")
})
//寫法2:
test (){ (str) in
print("\(str),world !")
}
//寫法3: (系統寫法)
test { (str) in
print("\(str),world !")
}
}
}
//測試函式
func test(bag:(str:String) ->()) {
print("test ---")
bag(str: "hello")
}