如何从方法的闭包中删除强引用循环? [英] How to remove strong reference cycle from closure from method?

查看:17
本文介绍了如何从方法的闭包中删除强引用循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里我有一些关闭强引用循环的例子.如果我为存储的属性分配一个闭包,我可以使用一个闭包捕获列表来使捕获的引用成为无主/弱引用.但是,如果我将方法分配给存储属性闭包或将方法分配给外部作用域中的闭包,我将无法使用捕获列表.

在最后两种情况下,如何去除引用循环?

仅使用带闭包的捕获列表创建和避免强引用循环的示例

内部类ClosureClass {内部让 p1:字符串内部惰性 var p2: () ->字符串 = {[unowned self]//如果你把它注释掉,就会有一个强引用循环() ->串入返回 self.p1}内部初始化(){self.p1 = "ClosureClass 的默认值"}取消初始化{print("带有属性 '(self.p1)' 的对象正在被取消初始化")}}打印(测试'关闭强引用自我':")var cc:ClosureClass?= ClosureClass.init()cc!.p2()//懒惰需要调用一次,否则不会初始化cc = 零

使用方法的闭包创建强引用循环的示例

内部类 MethodToClosureClass {内部让 p1:字符串内部惰性 var p2: () ->String = method(self)//为什么不是 self.method ?将创建一个强引用循环,但我不能像在闭包捕获列表中那样将引用设置为弱或无主内部初始化(){self.p1 = "MethodToClosureClass 的默认值"}内部函数方法() ->细绳 {//[无主自我] in返回 self.p1}取消初始化{print("带有属性 '(self.p1)' 的对象正在被取消初始化")}}打印(测试'使用方法实习生设置闭包':")var m2cc:MethodToClosureClass?= MethodToClosureClass.init()m2cc!.p2()//懒惰需要调用一次,否则不会初始化m2cc = 零

通过从外部方法设置闭包来创建强引用循环的示例

内部类 MethodClass {内部让 p1:字符串内部变量 p2: () ->字符串 = {返回 ""}内部初始化(){self.p1 = "MethodClass 的默认值"}内部函数方法() ->细绳 {//[无主自我] in返回 self.p1}取消初始化{print("带有属性 '(self.p1)' 的对象正在被取消初始化")}}print("Test 'Setclosure with method extern':")var mc:方法类?= MethodClass.init()var 方法:() ->String = mc!.method//将创建一个强引用mc!.p2 = 方法mc = 零

输出

<块引用>

测试对自身进行强引用的闭包":

正在取消初始化具有ClosureClass 的默认值"属性的对象

测试使用方法实习生设置闭包":

测试使用方法 extern 设置闭包":

解决方案

self.method 只是一个创建闭包的语法糖(使用默认的捕获模式,很强大):{ () in self.method() }.如果您想使用显式捕获列表,请不要使用语法糖 - 显式创建一个闭包(无论如何它都是这样做的):

{ [unowned self] () in self.method() }

Here I have some examples for closure strong reference cycles. If I assign a closure to a stored property, I can use a closure capture list to make the captured reference unowned/weak. But if I assign a method to a stored property closure or assign the method to a closure in the outer scope I can not use a capture list.

What can I do to remove the reference cycle in the last two cases?

Example to create and avoid strong reference cycle with capture list with closure only

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

Example to create strong reference cycle with closure from method

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

Example to create strong reference cycle with setting closure from method from 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

Output

Test 'Closure with strong reference to self':

Object with property 'Default value of ClosureClass' is being deinitialized

Test 'Set closure with method intern':

Test 'Set closure with method extern':

解决方案

self.method is just a syntactic sugar for creating a closure (with the default capture mode, which is strong): { () in self.method() }. If you want to use an explicit capture list, don't use the syntactic sugar -- create a closure (which is what it does anyway) explicitly:

{ [unowned self] () in self.method() }

这篇关于如何从方法的闭包中删除强引用循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆