候选人不是'@objc',但协议要求

我一直在关注这个教程来学习Swift和iOS应用程序开发。 在“协议”部分,教程定义了以下协议:

@objc protocol Speaker { func Speak() optional func TellJoke() } 

它说如果你想有一个可选方法的协议,你必须在协议前加上@objc标签(即使你的类没有与objective-C进行交互操作)

然后,它显示了实现该协议的示例:

 class Vicki: Speaker { func Speak() { println("Hello, I am Vicki!") } func TellJoke() { println("Q: What did Sushi A say to Sushi B?") } } 

我尝试了上述代码在我的Xcode操场,但我得到了编译器错误“typesVicki不符合协议扬声器”

Xcode也popup一个修复它的文本说: “候选人不是'@objc',但协议要求它”

我现在完全混淆了,教程没有提到这个错误。 有人能向我解释一切吗? 谢谢!

从我所知道的,把你的协议标记为@objc意味着任何实现它的类也必须暴露给Objective-C。 这可以通过使Vicki成为NSObject的一个子类来完成:

 class Vicki: NSObject, Speaker { 

或者将每个实现的方法标记为@objc:

 class Vicki: Speaker { @objc func Speak() { print("Hello, I am Vicki!") } @objc func TellJoke() { print("Q: What did Sushi A say to Sushi B?") } } 

更新:从Apple的Swift语言文档

可选协议要求只能在您的协议使用@objc属性标记时指定。

还要注意,@objc协议只能由类来采用,而不能通过结构或枚举。 如果您将协议标记为@objc以指定可选要求,则只能将该协议应用于类types。

为了使types符合标记为@objc的协议,该types还必须标记@objc或用于满足协议的方法必须是。

在声明中使用@objc告诉编译器将其暴露给Objective-C运行时。 为了做到这一点,声明为@objc的types必须能够在Objective-C中表示。

对于类来说,这意味着它们必须从NSObjectinheritance。 对于方法来说,这意味着它们被dynamic的Objective-C消息传递所支持。

看起来我们只需要在私有类中使用@objc前缀协议方法。

 private class A: NSObject, SomeObjcProtocol { @objc func someProtocolMethod() {} } 

对于非私人课堂,警告的可能性不大。

 class A: NSObject, SomeObjcProtocol { func someProtocolMethod() {} } 

两者都很好。

为返回空函数和默认值的协议添加一个扩展。 任何符合协议并希望覆盖任何func或var的类都可以select这样做。

  public protocol Speaker { func Speak() func TellJoke() } extension Speaker { func Speak() {} func TellJoke() { print("What did the Teabag say to the Octopus?"} } 

奖金是你不inheritance所有的物品的行李。