如何在'纯粹的'Swift(w / o @objc)中创build一个弱协议引用

weak引用似乎没有在Swift中工作,除非一个protocol被声明为@objc ,我不想在一个纯粹的Swift应用程序。

此代码给出了编译错误( weak不能应用于非types的MyClassDelegate ):

 class MyClass { weak var delegate: MyClassDelegate? } protocol MyClassDelegate { } 

我需要以@objc作为前缀,然后才能正常工作。

问:什么是“纯粹”的快速完成weak delegate

您需要将协议的types声明为class

 protocol ProtocolNameDelegate: class { // Protocol stuff goes here } class SomeClass { weak var delegate: ProtocolNameDelegate? } 

我的理解是,使用class ,你保证这个协议将只用于类,没有其他东西像枚举或结构。

补充答案

我一直对代表是否应该软弱感到困惑。 最近我已经学到了更多关于代表和什么时候使用弱引用的内容,所以为了未来的观众,我在这里补充一些补充点。

  • 使用weak关键字的目的是为了避免强参考周期(保留周期)。 当两个类实例具有强相互引用时,强引用周期发生。 他们的引用计数永远不会归零,所以他们永远不会被释放。

  • 如果委托是一个类,则只需使用weak 。 Swift结构和枚举是值types(它们的值在新实例制作时被复制),而不是引用types,所以它们不会产生强的引用周期。

  • weak引用总是可选的(否则你将使用unowned ),并总是使用varlet ),以便可选项可以设置nil时,它被释放。

  • 一个父类自然应该有一个强types的子类,因此不使用weak关键字。 当一个孩子想要引用它的父母时,应该使用weak关键字来使它成为一个弱引用。

  • 当你想引用一个你不拥有的类时,应该使用weak ,而不仅仅是引用其父类的子类。 当两个非层次类需要相互引用时,select一个弱。 你select的取决于情况。 请参阅此问题的答案以了解更多信息。

  • 作为一般规则,代表应该被标记为weak因为大多数代表正在引用他们不拥有的类。 当孩子使用委托与父母沟通时,这当然是正确的。 但是,在某些情况下 ,代表可以并应该使用强有力的参考。

  • 协议可以用于引用types(类)和非引用types(结构体,枚举)。 因此,在需要使委托变弱的可能情况下,您必须将class关键字添加到协议中,以便它知道仅用于引用types。

     protocol MyClassDelegate: class { // ... } class SomeClass { weak var delegate: MyClassDelegate? } 

进一步研究

阅读以下文章是帮助我更好地理解这一点的。 他们还讨论相关的问题,如unowned关键字和强大的引用周期发生在closures。

  • Swift文档: 自动引用计数
  • “弱,强,无主,我的!” – Swift参考指南
  • 强,弱,无主 – sortingARC和Swift

有关

  • 如何在Swift中创build代表
  • iOS:如何在Swift中制作弱代表
  • Swift委托 – 何时在委托上使用弱指针

更新:它看起来像手册已经更新,我所指的例子已被删除。 请参阅上面编辑@ flainez的回答。

原文:即使您不与Obj-C互操作,使用@objc也是正确的做法。 它确保你的协议被应用到一个类,而不是一个枚举或结构。 请参阅手册中的“检查协议一致性”。

苹果使用“NSObjectProtocol”而不是“class”。

 public protocol UIScrollViewDelegate : NSObjectProtocol { ... } 

这也适用于我,并删除我试图实现我自己的委托模式时看到的错误。