弱引用似乎在Swift中不起作用,除非协议声明为@objc,这是我不希望在纯Swift应用程序中使用的。

这段代码给出了一个编译错误(weak不能应用于非类类型MyClassDelegate):

class MyClass {
  weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate {
}

我需要用@objc作为协议的前缀,然后它就可以工作了。

问:完成弱委托的“纯”Swift方式是什么?


当前回答

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

public protocol UIScrollViewDelegate : NSObjectProtocol {
   ...
}

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

其他回答

AnyObject是Swift中使用弱引用的官方方式。

class MyClass {
    weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate: AnyObject {
}

从苹果公司:

为了防止强引用循环,委托应该声明为 弱引用。有关弱引用的详细信息,请参见 类实例之间的强引用循环。标记协议 As -only稍后将允许您声明委托必须 使用弱引用。将协议标记为仅类 从AnyObject继承,如仅类协议中所述。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276

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

public protocol UIScrollViewDelegate : NSObjectProtocol {
   ...
}

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

补充回答

我总是困惑于委托是否应该是弱的。最近,我了解了更多关于委托和何时使用弱引用的知识,因此,为了将来的观众,让我在这里补充一些要点。

The purpose of using the weak keyword is to avoid strong reference cycles (retain cycles). Strong reference cycles happen when two class instances have strong references to each other. Their reference counts never go to zero so they never get deallocated. You only need to use weak if the delegate is a class. Swift structs and enums are value types (their values are copied when a new instance is made), not reference types, so they don't make strong reference cycles. weak references are always optional (otherwise you would used unowned) and always use var (not let) so that the optional can be set to nil when it is deallocated. A parent class should naturally have a strong reference to its child classes and thus not use the weak keyword. When a child wants a reference to its parent, though, it should make it a weak reference by using the weak keyword. weak should be used when you want a reference to a class that you don't own, not just for a child referencing its parent. When two non-hierarchical classes need to reference each other, choose one to be weak. The one you choose depends on the situation. See the answers to this question for more on this. As a general rule, delegates should be marked as weak because most delegates are referencing classes that they do not own. This is definitely true when a child is using a delegate to communicate with a parent. Using a weak reference for the delegate is what the documentation recommends. (But see this, too.) Protocols can be used for both reference types (classes) and value types (structs, enums). So in the likely case that you need to make a delegate weak, you have to make it an object-only protocol. The way to do that is to add AnyObject to the protocol's inheritance list. (In the past you did this using the class keyword, but AnyObject is preferred now.) protocol MyClassDelegate: AnyObject { // ... } class SomeClass { weak var delegate: MyClassDelegate? }

进一步的研究

阅读下面的文章有助于我更好地理解这一点。他们还讨论了相关的问题,如无主关键字和闭包发生的强引用循环。

委托文件 快速文档:自动引用计数 “弱,强,无主,天哪!”- Swift参考指南 强,弱,和无主-整理ARC和Swift

相关的

如何在Swift中制作委托 iOS:如何在Swift中创建弱委托 Swift委托-何时在委托上使用弱指针

protocol必须是AnyObject的子类,class

示例如下

    protocol NameOfProtocol: class {
   // member of protocol
    }
   class ClassName: UIViewController {
      weak var delegate: NameOfProtocol? 
    }

您需要将协议的类型声明为AnyObject。

protocol ProtocolNameDelegate: AnyObject {
    // Protocol stuff goes here
}

class SomeClass {
    weak var delegate: ProtocolNameDelegate?
}

使用AnyObject,你说只有类可以符合这个协议,而结构或枚举不能。