Как удалить сильный контрольный цикл из замыкания из метода?
Здесь у меня есть несколько примеров закрытия сильных референтных циклов. Если я назначу замыкание на сохраненное свойство, я могу использовать список захвата замыкания, чтобы сделать захваченную ссылку неизвестной / слабой. Но если я назначу метод закрытию хранимого свойства или назначу метод закрытию во внешней области, я не смогу использовать список захвата.
Что я могу сделать, чтобы удалить контрольный цикл в двух последних случаях?
Пример создания и избежания сильного ссылочного цикла со списком захвата только с закрытием
internal class ClosureClass {
internal let p1: String
internal lazy var p2: () -> String = {
[unowned self] // if you comment this out there is a strong reference cycle
() -> String in
return self.p1
}
internal init() {
self.p1 = "Default value of ClosureClass"
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Closure with strong reference to self':")
var cc: ClosureClass? = ClosureClass.init()
cc!.p2() // lazy need to call it once, else it will not be initiliazed
cc = nil
Пример создания сильного ссылочного цикла с замыканием из метода
internal class MethodToClosureClass {
internal let p1: String
internal lazy var p2: () -> String = method(self) // Why not self.method ? Will create a strong reference cycle, but I can not set the reference to weak or unowned like in closures with the closure capture list
internal init() {
self.p1 = "Default value of MethodToClosureClass"
}
internal func method() -> String {
// [unowned self] in
return self.p1
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Set closure with method intern':")
var m2cc: MethodToClosureClass? = MethodToClosureClass.init()
m2cc!.p2() // lazy need to call it once, else it will not be initiliazed
m2cc = nil
Пример создания сильного ссылочного цикла с настройкой закрытия из метода из extern
internal class MethodClass {
internal let p1: String
internal var p2: () -> String = {
return ""
}
internal init() {
self.p1 = "Default value of MethodClass"
}
internal func method() -> String {
// [unowned self] in
return self.p1
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Set closure with method extern':")
var mc: MethodClass? = MethodClass.init()
var method: () -> String = mc!.method // will create a strong reference
mc!.p2 = method
mc = nil
Выход
Тест "Закрытие с сильной ссылкой на себя":
Объект со свойством 'Значение по умолчанию ClosureClass' деинициализируется
Тест "Установить замыкание с помощью метода intern":
Тест "Установить замыкание методом extern":
1 ответ
self.method
это просто синтаксический сахар для создания замыкания (с режимом захвата по умолчанию, который является сильным): { () in self.method() }
, Если вы хотите использовать явный список перехвата, не используйте синтаксический сахар - создайте замыкание (что он и делает в любом случае) явно:
{ [unowned self] () in self.method() }