클로저에 대한 강한 참조 사이클
- 강한 참조 사이클은 클래스 인스턴스의 프로퍼티에 클로저를 할당하고 해당 클로저의 바디에 인스턴스를 캡처하는 경우에도 발생한다. 이 캡처는 self.someProperty처럼 인스턴스의 프로퍼티에 접근하거나 클로저는 self.someMethod()와 같이 인스턴스 메서드를 호출하기에 발생할 수 있다. 이는 모두 클로저가 self를 "캡쳐" 하므로 생기는 강한참조 사이클이다.
- 이 강한 참조 사이클은 클로저와 클래스 모두 참조타입이므로 발생한다. 어떠한 프로퍼티에 클로저를 할당하면 해당 클로저에 참조를 할당하는 것이다.
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("this is deinited")
}
}
var paragraph : HTMLElement? = HTMLElement(name : "p", text : "Hello world")
print(paragraph!.asHTML())
paragraph = nil
클로저에 대한 약한 참조와 미소유 참조
- 클로저에 캡처한 인스턴스가 항상 서로를 참조하고 항상 같은 시간에 할당 해제될 때 클로저의 캡처를 미소유 참조로 정의한다.
- 반대로 캡처된 참조가 향후 nil이 되는 경우엔 약한 참조로 캡처를 정의한다.
- 캡처된 참조가 nil이 안되려면 약한 참조보다 미소유 참조로 캡처되어야 한다.
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("deinitialized")
}
}
var paragraph : HTMLElement? = HTMLElement(name : "P", text : "Hello world")
print(paragraph!.asHTML())
paragraph = nil