功能编程:闭包参考周期和修复

Article_1链接→ 功能迅速:关于闭包的全部。

Article_2链接→ iOS中的Lazy var swift。

请阅读以上两篇文章以继续。


假设您对函数式编程和闭包有很好的了解,那么让我们开始吧。

考虑一类Human 。 它具有一个init方法,该方法接受firstNamelastName作为参数。 它还有一个名为fullNamelazy var closure ,该lazy var closure不接受任何内容并返回String 。 它是()->String类型的。

在这里,当我们调用init方法时,将创建一个新的Human对象。 我们将此对象分配给可选类型humanObj

在下一行中,当我们将humanObj的值设置为nil ,将deinit{}方法。 您可以看到控制台打印在deinit方法中给出的文本。

现在,尝试在创建对象之后访问fullName闭包。 然后尝试将对象设置为nil

  var humanObj:人类?  = Human(firstName:“ John”,lastName:“ Doe”) let fullName = humanObj?.fullName humanObj = nil 

由于闭包强烈引用self因此不会调用deinit{}方法。

释放对象时将调用deinit方法。

解决方法

我们可以在捕获列表中使用self来使用weak引用或unowned引用来打破强引用周期。 如果您不知道什么是捕获列表,请阅读顶部提到的文章。

弱引用是指不会对其引用的实例保持强大控制的引用,因此不会阻止ARC处置所引用的实例。 此行为可防止参考成为强大参考周期的一部分。

由于弱引用可能为nil ,因此捕获的变量变为可选。 因此,我们应该使用guard来安全地拆开它:

  懒惰的var fullName :()->字符串= {保护中的[弱自我] 让weakSelf =自我else {返回“”} 返回“ \(weakSelf.firstName)\(weakSelf.lastName)” } 

无人

像弱引用一样,无主引用也不会对其引用的实例保持强大的控制力。 但是,与弱引用不同,当另一个实例具有相同的生存期或更长的生存期时,将使用无主引用

  惰性var fullName :()->字符串= { 返回[\(self.firstName)\(self.lastName)”的[无名的 自我] } 

这意味着,当我们确定引用在闭包内永远不会nil时,我们应该使用unowned ,否则应用程序将崩溃。 因此,此处不需要进行防护检查。

我们可以对捕获列表中的任何变量使用weakunowned ,并可以与别名结合使用:

  惰性var fullName :()->字符串= { 返回[\(unownedSelf.firstName)\(unownedSelf.lastName)” } 

如何用带有参数的闭包捕获自我?

好吧,您应该在内部闭包参数之前或内部参数括号之前捕获self检查下面的代码。 它说明了如何在单个参数的情况下捕获自身。 如果您有多个参数,则也可以使用括号。

重要提示:对于非转义的闭包,我们不必担心使用弱关键字或无主关键字来捕获自身。 它仅对转义的闭包有意义。

例外情况:

尽管在封闭中弱地捕获self是一种好习惯,但并非总是必要的。 没有self保留的封闭物可以很强地捕获它,而不会引起保留循环。 一些常见的例子是:

使用DispatchQueue ,GCD中的animation关闭

 DispatchQueue.main.async { self.doSomething() // Not a retain cycle }  DispatchQueue.main.async { self.doSomething() // Not a retain cycle } UIView.animate(withDuration: 1) { self.doSomething() // Not a retain cycle } UIView.animate(withDuration: 1) { self.doSomething() // Not a retain cycle } 

不需要强烈捕获self另一个有趣的地方是lazy变量,它们不是闭包,因为它们将运行一次(或永远不会运行),然后再释放:

 lazy var fullName = { return self.firstName + " " + self.lastName }() // not retained. no need to use self with weak or unowned 

但是, 如果一个 lazy 变量是一个闭包 ,则需要捕获自身weakly/unowned 。 Human类中的fullName:()->String闭包就是一个很好的例子。

请享用!!

如果您喜欢阅读这篇文章,请分享并推荐它,以便其他人可以找到💚💚💚💚💚💚!!!!

您可以在Medium上关注我以获取新文章。 在LinkedIn上与我联系。

如果您有任何评论,问题或建议,请随时在下面的评论部分中发布它们!

分类 雨燕 标签 关闭 , iOS , Swift ,无主, 弱