Swift 关于闭包强引用循环的困惑? 类HtmleElement{ let name:String 让文本:字符串? //声明具有此闭包的强引用的惰性变量 惰性变量asHTML:Void->String={ //这里的可选绑定 如果let text=self.text{ 返回“\(文本)” }否则{ 返回“” } } init(名称:String,文本:String?=nil){ self.name=名称 self.text=文本 } 脱硝{ 打印(\(名称)正在取消初始化) } }

Swift 关于闭包强引用循环的困惑? 类HtmleElement{ let name:String 让文本:字符串? //声明具有此闭包的强引用的惰性变量 惰性变量asHTML:Void->String={ //这里的可选绑定 如果let text=self.text{ 返回“\(文本)” }否则{ 返回“” } } init(名称:String,文本:String?=nil){ self.name=名称 self.text=文本 } 脱硝{ 打印(\(名称)正在取消初始化) } },swift,reference,closures,automatic-ref-counting,strong-references,Swift,Reference,Closures,Automatic Ref Counting,Strong References,我的问题是:为什么闭包被声明为Lazy,我知道它与闭包中不知道的self有关,但是对于init方法,如果没有创建self,情况不是一样吗 其次,在本代码示例中,强引用循环的确切位置是哪里?强引用asHTML的是self,如果是,导致该循环的强引用的第二部分在哪里 第三,当常量无法更改值(从nil更改为值并返回到nil)时,为什么常量text属性是可选的 最后,使用参数text:String意味着什么当init方法用于接受用户发送的参数时,是否在init方法中使用nil 很抱歉问这么长的问题,我只

我的问题是:为什么闭包被声明为Lazy,我知道它与闭包中不知道的
self
有关,但是对于
init
方法,如果没有创建
self
,情况不是一样吗

其次,在本代码示例中,强引用循环的确切位置是哪里?强引用asHTML的是
self
,如果是,导致该循环的强引用的第二部分在哪里

第三,当常量无法更改值(从
nil
更改为值并返回到
nil
)时,为什么常量
text
属性是可选的

最后,使用参数
text:String意味着什么当
init
方法用于接受用户发送的参数时,是否在
init
方法中使用nil

很抱歉问这么长的问题,我只是对闭包强引用循环感到困惑……尽管我确实理解类属性和类实例之间的强引用循环。

1

lazy
用于仅在调用时创建的属性。因此,在调用
myClass.myLazyAttribute
之前,它不会占用任何空间。这也意味着它将在类初始化后初始化,这可能非常有用

在这种情况下,如您所述,
lazy
用于访问
self
,因为在初始化实例之前,
self
不可用

2

闭包捕获其中使用的值。在本例中,它捕获
自身
。
它不会在类a和类B之间创建一个强引用循环,而是在类本身和闭包之间创建一个强引用循环。如果您认为闭包内的操作需要很长时间,那么这就更有意义了。在执行过程中,发生了其他一些事情,您希望对该实例进行反硝化。但是闭包捕获了
self
,它将使实例保持活动状态,直到完成为止

通过在
中使用
[unowned self],您可以在闭包运行时再次对实例进行反硝化。虽然这会使你的应用程序崩溃

有关此特定用途的详细信息:

在闭包的特定情况下,您只需要认识到在闭包中引用的任何变量都会被闭包“拥有”。只要闭包存在,这些对象就一定存在。阻止这种所有权的唯一方法是做[无主的自我]或[软弱的自我]

强引用周期的本质是什么:

  • 您有一个类的实例
  • 实例的引用计数大于0
  • 您的程序不再有对实例的引用
甚至更短:实例的引用计数高于可访问引用的数量

在这种情况下,
self
的引用计数增加1,因为它被闭包捕获。我们无法访问该引用,因为我们无法说出类似以下内容:
closure.selfAttribute
,因此无法将其设置为
nil
。只有当闭包完成时,引用计数才会再次下降1

3

它是一个可选常量,但它的初始值是在类的init方法中设置的。因此,它可以在init方法中接收一个值,但它是不可变的。这称为后期初始化

4

这是一个具有默认值的函数参数

class HTMLElement {

    let name : String
    let text: String?

    //Declaring a lazy variable that has a strong reference to this closure
    lazy var asHTML: Void -> String = {
        //Optional binding here
        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")
    }
}

请注意,不仅
weak
,而且
unowned
也不是强引用。现在我有一个问题,如果我创建
HTMLElement
类的实例,文档中说将有一个强引用循环,我理解它们的一半含义…….闭包使用self.name和self.text来“捕获”self并对
HTMLElement
类的实例进行了强引用…..现在如何从实例返回到闭包的强引用???@Ali那么我需要知道另一面是什么样子。这段代码来自哪里。你提到了文档,那么这是一个教程还是一个框架呢?这直接来自苹果的文档:{[@Fawkes抱歉这么晚才回复。如果你在一个闭包中捕获了
self
,而这个闭包是一个很长的操作(网络请求)操作完成后,不再有任何其他对
self
的引用
self
将被解除分配。
func someFunction(myParamWithDefaultValue : Int = 10) {
    print(myParamWithDefaultValue)
}

someFunction() // 10
someFunction(5) // 5