介紹
-
閉包和OC中的block非常相似
- OC中的block是匿名的函數
- Swift中的閉包是一個特殊的函數
- block和閉包都經常用于回調
block寫法總結:參考
類型:
返回值(^block的名稱)(block的參數)
值:
^(參數列表) {
// 執行的代碼
};
- 閉包的寫法總結:
閉包的寫法:
類型:(形參列表)->(返回值)
技巧:初學者定義閉包類型,直接寫()->().再填充參數和返回值
值:
{
(形參) -> 返回值類型 in
// 執行代碼
}
基本使用
- 定義網絡請求類
class HttpTool: NSObject {
func loadRequest(callBack : ()->()){
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("加載數據", [NSThread.currentThread()])
dispatch_async(dispatch_get_main_queue(), { () -> Void in
callBack()
})
}
}
}
- 進行網絡請求,請求到數據后利用閉包進行回調
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// 網絡請求
httpTool.loadRequest ({ () -> () in
print("回到主線程", NSThread.currentThread());
})
}
閉包賦值的寫法
/*
給閉包賦值:
{
(參數) -> (返回值) in
// 代碼塊
}
*/
httpTool.requestData ({ () -> () in
print("已經請求到網絡數據");
print("更新界面:\(NSThread.currentThread())")
})
- 如果閉包沒有參數,沒有返回值.in和in之前的內容可以省略
httpTool.loadRequest({
print("回到主線程", NSThread.currentThread());
})
- 尾隨閉包寫法:
- 如果閉包是函數的最后一個參數,則可以將閉包的()寫在{}前面
httpTool.requestData () { () -> () in
print("已經請求到網絡數據");
print("更新界面:\(NSThread.currentThread())")
}
- 如果函數只有一個參數,并且這個參數是閉包,那么()可以不寫
httpTool.requestData { () -> () in
print("已經請求到網絡數據");
print("更新界面:\(NSThread.currentThread())")
}
循環引用
- 如果在HttpTool中有對閉包進行強引用,則會形成循環引用
class HttpTool: NSObject {
// 定義屬性,來強引用傳入的閉包
var callBack : (()->())?
func loadRequest(callBack : ()->()){
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("加載數據", [NSThread.currentThread()])
dispatch_async(dispatch_get_main_queue(), { () -> Void in
callBack()
})
}
self.callBack = callBack
}
}
- 解決方法
- 方法一:
weak var weakSelf : ViewController? = self
httpTool.requestData {
print("更新界面:\(NSThread.currentThread())")
weakSelf!.view.backgroundColor = UIColor.orangeColor()
}
- 方法二:
// 該方式不能省略賦值時的:() -> () in
httpTool.requestData { [weak self] () -> () in
print("更新界面:\(NSThread.currentThread())")
self!.view.backgroundColor = UIColor.orangeColor()
}
- 方法三:該方法容易產生野指針,不建議使用
// 該方式不能省略賦值時的:() -> () in
httpTool.requestData { [unowned self] () -> () in
print("更新界面:\(NSThread.currentThread())")
self.view.backgroundColor = UIColor.orangeColor()
}
補充
- Swift中沒有dealloc方法
- 析構函數:相當于OC中dealloc.也是對象銷毀時會調用函數