swift我应该使用协议还是协议:class

use*_*197 40 swift swift-protocols

我已经设置了一个协议,将一些信息发送回以前的VC.

我这样定义它:

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

但使用时有什么区别:

protocol FilterViewControllerDelegate  {
        func didSearch(Parameters:[String: String]?)
    }
Run Code Online (Sandbox Code Playgroud)

我什么时候应该使用: class协议?

Luc*_*tti 50

Swift 4版

AnyObject 添加到这样的协议定义中

protocol FilterViewControllerDelegate: AnyObject  {
    func didSearch(parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

意味着只有一个类才能符合该协议.

所以这个

protocol FilterViewControllerDelegate: AnyObject  {
    func didSearch(parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

你可以写这个

class Foo: FilterViewControllerDelegate {
    func didSearch(parameters:[String: String]?) { }
}
Run Code Online (Sandbox Code Playgroud)

不是这个

struct Foo: FilterViewControllerDelegate {
    func didSearch(parameters:[String: String]?) { }
}
Run Code Online (Sandbox Code Playgroud)

Swift 3版

:class 添加到这样的协议定义中

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

意味着只有一个类才能符合该协议.

所以这个

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

你可以写这个

class Foo: FilterViewControllerDelegate {
    func didSearch(Parameters:[String: String]?) { }
}
Run Code Online (Sandbox Code Playgroud)

不是这个

struct Foo: FilterViewControllerDelegate {
    func didSearch(Parameters:[String: String]?) { }
}
Run Code Online (Sandbox Code Playgroud)


小智 23

使用'class'关键字标记协议还有另外一件事.

这是你的协议:

protocol FilterViewControllerDelegate: class  {
    func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

例如,假设您正在创建一个具有委托属性的DetailVC:

class DetailViewController: UISomeViewController {
    weak var delegate: FilterViewControllerDelegate
}
Run Code Online (Sandbox Code Playgroud)

如果您不使用"class"关键字标记该协议,您也无法将该"委托"属性标记为"弱"属性.

为什么?

这很简单 - 只有基于类的属性才能有弱关系.如果您试图避免参考周期,那就是要走的路

  • 到目前为止,这是我读过的最好的答案。每个人都在说它的意思,但没人说为什么要使用它。谢谢! (2认同)

swi*_*eek 9

Swift 4.1,Xcode 9.3语法:

protocol FilterViewControllerDelegate: AnyObject {
       func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

该协议只能由类采用.

回答你的第一个问题 -

但使用时有什么区别:

与此不同的是:

protocol FilterViewControllerDelegate  {
        func didSearch(Parameters:[String: String]?)
}
Run Code Online (Sandbox Code Playgroud)

是这个协议可以采用值类型,如枚举和结构.

回答你的第二个问题 -

什么时候应该使用:class protocal?

当你应该使用类协议时,我想从委托模式描述下一个例子:想象一下你有委托协议.

protocol PopupDelegate: AnyObject {
    func popupValueSelected(value: String)
}
Run Code Online (Sandbox Code Playgroud)

在另一个类中,您要创建一个属性

var delegate: PopupDelegate?
Run Code Online (Sandbox Code Playgroud)

但这有很强的参考,可以带来内存泄漏的问题.修复内存泄漏的一种方法是使委托属性 - 弱.在我们不能使我们的协议仅用于申请课程之前,Swift认为我们也可以将我们的协议应用于价值类型.

weak var delegate: PopupDelegate?
Run Code Online (Sandbox Code Playgroud)

如果您尝试将您的委托声明为弱,您将看到下一个错误:

'weak'var只适用于类和类绑定协议类型,而不是'PopupDelegate'

但我们不能将弱值应用于价值类型.所以我们需要将协议限制为引用类型,因此swift知道它是一个引用类型.为了使您可以将此委托声明为弱,您需要限制仅由类使用的协议:

protocol PopupDelegate: AnyObject {
    func popupValueSelected(value: String)
}
Run Code Online (Sandbox Code Playgroud)


ale*_*nik 5

这意味着您定义的协议只能由类,而不是结构或枚举来采用.

来自官方Swift书:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here } 
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,SomeClassOnlyProtocol只能由类类型采用.编写尝试采用SomeClassOnlyProtocol的结构或枚举定义是编译时错误.