-
strong:當(dāng)你聲明一個屬性時,它默認(rèn)就是強引用 -
weak:弱引用對象的引用計數(shù)不會+1, 必須為可選類型變量
在聲明弱引用對象是必須用var關(guān)鍵字, 不能用let.
因為弱引用變量在沒有被強引用的條件下會變?yōu)閚il, 而let常量在運行的時候不能被改變.
class XDTest {
//會報錯
weak let tentacle = Tentacle() //let is a constant! All weak variables MUST be mutable.
}
-
unowned:相當(dāng)于__unsafe_unretained, 不安全. 必須為非可選類型.
unowned引用是non-zeroing(非零的), 在ARC銷毀內(nèi)存后,不會被賦為nil, 這表示著當(dāng)一個對象被銷毀時, 它指引的對象不會清零. 也就是說使用unowned引用在某些情況下可能導(dǎo)致dangling pointers(野指針). 所以在訪問無主引用的時候,要確保其引用正確,不然會引起內(nèi)存崩潰.
-
隱式解析可選類型:語法是在變量后面加上感嘆號(例如var name:String!). 在初始的時候可以為nil, 但是第一次賦值以后便會一直有值. 使用該類型只需要正常調(diào)用, 不需要像可選類型那樣解包.
避免在閉包中循環(huán)引用
在閉包中, 要拿到對象本身的屬性, 必須要用到self關(guān)鍵字.
導(dǎo)致block對對象進行了強引用, 而對象本身對block也是強引用, 這樣就形成了循環(huán)引用. (Self <-> Block)
- 解決辦法和OC中一樣, 將強引用self變?yōu)槿跻胹elf.
OC中解決辦法是__weak SelfClass *weakSelf = self;
在Swift中類似的解決辦法是(解決方式一)weak var weakSelf = self - 使用捕獲列表(在其定義的上下文中捕獲常量或變量, 即使定義這些常量和變量的原域已經(jīng)不存在, 閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值.)
蘋果官方語言指南要求如果閉包和其捕獲的對象相互引用, 應(yīng)該使用unowned, 這樣可以保證他們會同時被銷毀. 大概是為了避免對象被釋放后維護weak引用空指針的開銷.
格式:在閉包前面加上[unowned 想要捕獲的變量]
官方文檔中的例子:
有參數(shù)和返回值的block
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
無參數(shù)和返回值的block
lazy var someClosure: Void -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
例子:
import UIKit
class ViewController: UIViewController {
var finishedCallBack: ( (dataString: String) -> () )?
override func viewDidLoad() {
super.viewDidLoad()
//解決方式三: [unowned self] 跟 _unsafe_unretained 類似
loadData { [unowned self] (dataString) -> () in
print("\(dataString) \(self.view)")
}
}
func method2() {
//解決方式二: 在swift中 有特殊的寫法 [weak self]
loadData { [weak self] (dataString) -> () in
//以后在閉包中中 使用self 都是若引用的
print("\(dataString) \(self?.view)")
}
}
func method1() {
// 解決方式一: weak , OC中類似方法__weak
weak var weakSelf = self
loadData { (dataString) -> () in
print("\(dataString) \(weakSelf?.view)")
}
}
func loadData(finished: (dataString: String) -> ()) {
// 記錄閉包
self.finishedCallBack = finished
//加載數(shù)據(jù)
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("執(zhí)行耗時操作")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//執(zhí)行回調(diào)
self.working()
})
}
}
func working() {
self.finishedCallBack?(dataString: "<html>")
}
//swift dealloc
//析構(gòu)函數(shù)
deinit {
print("銷毀")
}
}