这两个代表声明有什么区别?



我正在学习委托,我不明白为什么

let friendsFunctionsDelegate = FriendsFunctionsDelegate()
let friendsFunctions = FriendsFunctions()
friendsFunctionsDelegate.delegate = friendsFunctions

是正确的,而

let friendsFunctionsDelegate = FriendsFunctionsDelegate()
friendsFunctionsDelegate.delegate = FriendsFunction()

是错误的。

下面是完整的代码:

protocol FriendsDelegate: AnyObject {
func orderPizza()
func takeABreak()
}
class FriendsFunctionsDelegate {
weak var delegate: FriendsDelegate? = nil

func buyPizza() {
delegate?.orderPizza()
}

func sleep() {
delegate?.takeABreak()
}
}
class FriendsFunctions: FriendsDelegate {
func orderPizza() {
print("I ordered a pizza")
}

func takeABreak() {
print("I'm going to sleep")
}
}
let friendsFunctionsDelegate = FriendsFunctionsDelegate()
let friendsFunctions = FriendsFunctions()
friendsFunctionsDelegate.delegate = friendsFunctions

ARC (for Automatic Reference Counting)

是自动管理对象的内存分配/释放的系统。

的工作方式是,只要你有至少1对代码中对象的强引用将保留在内存中请注意,默认情况下,任何未定义为弱的属性定义都是隐式强的。

当指定一个属性为弱属性时,它不会增加"保持引用计数"。。

您遇到的问题…

在你的第一个例如,当您第一次创建let常量时,您保存一个引用,然后将其赋值给弱变量。=>

  1. 1对对象的弱引用(存储在friendsFunctionsDelegate.delegate上)
  2. 1强引用对象(let constantlet friendsFunctions = FriendsFunctions())

因此,ARC是NOT释放对象(强引用>= 1) =>它正在工作✅

例如,当您直接实例化+分配委托给弱变量时,没有首先创建一个常量。=>

  1. 1对对象的弱引用(存储在friendsFunctionsDelegate.delegate上)
  2. 0对对象的强引用

因此,ARC正在释放(从内存中释放)赋值后的对象(强引用== 0)=>不工作❌

结论

作为结论,您需要在某个地方保留对该委托对象的强引用。

委托模式中的弱用法

当使用委托时,我们使用弱属性来防止内存保留周期。当一个对象(对象A)持有对另一个对象(对象B)的强引用,而另一个对象(对象B)也有对第一个对象(对象A)的强引用时,就会发生这种情况。

  • =比;B强劲
  • B =比;一个强大的

=比;⚠️保留周期⚠️

当你试图从内存中删除对象A或B时,强引用计数将仍然为1,然后你将获得内存泄漏,内存中充满了未使用的对象,这可能导致可用的应用程序。解决方案是将这两个引用中的一个定义为弱引用(而不是两个)。当应用委托模式时,可以将持有委托引用的属性定义为weak。

一些额外的注释:

  1. 小心命名,可能会产生误导。delegate关键字应该只附加到协议后,而不是类名后。如果你删除它,虽然你会有重叠,这是一个暗示,命名可以更适当地定义。
  2. 当你将一个属性定义为Optional并且你希望它为nil作为默认值时,你不需要显式地指定= nil。虽然你仍然可以这样做;)
  3. 最佳实践告诉你,当你想要一个类符合委托/协议时,你应该使用一个扩展,而不是直接遵循类定义。
  4. 委托模式应该是一种盲通信模式,所以你的类不应该知道作用域外的函数。然后,委托方法的命名应该修改为func didBuyPizza()func didTakeABreak()或类似的东西。

let friendsFunctions = FriendsFunctions() // holds a strong reference
friendsFunctionsDelegate.delegate = friendsFunctions

可以工作,因为它保存了一个强引用,而

friendsFunctionsDelegate.delegate = FriendsFunction()

不能同时工作(lhs),rhs)是weak,所以没有保留发生(delegateweak属性)

注意FriendsFunctionsDelegate.delegate属性是一个弱引用:

weak var delegate: FriendsDelegate? = nil
^^^^

如果你做了

friendsFunctionsDelegate.delegate = FriendsFunction()

您创建了一个FriendsFunction对象,并且唯一有引用的对象是friendsFunctionsDelegate,通过它的delegate属性。但这是一个弱参考。没有对新的FriendsFunction对象的强引用!因此,它将在创建后立即被释放。

你应该在这里看到一个警告:

实例将立即被释放,因为属性'delegate'是'weak'

另一方面,如果您先将新创建的FriendsFunction对象放入let常量中,

let friendsFunctions = FriendsFunctions()

let常量friendsFunctions将是对FriendsFunctions对象的强引用,因为它不是weak。由于至少有一个强引用指向该对象,因此在所有强引用消失之前,该对象不会被释放。

更多信息请参见Swift指南中的自动引用计数。

相关内容

  • 没有找到相关文章

最新更新