swift中的arc与oc中很相似。需要注意的是swift中arc处理循环引用的关键字及其使用方式与oc中有所区分。循环引用在oc中,主要使用关键字weak或者unsafe_unretained来处理。在swift中使用weak和unowned来处理。
weak和unowned都表示不持有对象,区别在于,weak修饰的是optional的值,unowned修饰的是一定存在的值。也就是说weak修饰的var在运行时可以为nil,而unowned修饰的不可以。如果一个值使用unowned修饰,由于unowned修饰的值会自动解包,所以使用的时候,就不用加!符号了。
class instance中的使用例子
class Country {
let name: String
var capitalCity: City!
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.
Country和City类互相持有对方,如果不加unowned关键字,就会形成循环引用。如果City规定country属性不是必须有,则修饰的关键字可以改成weak,但是同时let也必须改成var,因为在运行时country可能有值,也可能为nil。
closure中的使用例子
如果closure赋值给一个var,然后在closure中又使用了类中的property等,那么会造成循环引用。例如:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
//使用
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Prints "<p>hello, world</p>
摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.
其内存引用关系为:
破除这么循环引用的方式是添加capture list。如下所示:
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.
这个capture list放在closure的参数和返回值之前。
如果closure没有参数和返回值,那么需要这样写:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.
通过in关键字将capture list和其他部分隔离开。上面这个例子中,改成如下方式就可以解除循环引用:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.