候选人不是' @ objc'但协议需要它

时间:2015-08-11 12:27:07

标签: ios xcode swift

我一直关注这个tutorial来学习快速和iOS应用开发。在Protocol部分,本教程定义了以下协议:

@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 playground中尝试了上面的代码,但是我得到了编译器错误" Type Vicki并不符合协议Speaker"

Xcode还会弹出修复文字,上面写着"候选人不是' @ objc'但协议需要它"

我现在感到很困惑,教程根本没有提到这个错误。有人可以向我解释这一切让我明白吗?谢谢!

4 个答案:

答案 0 :(得分:10)

据我所知,将协议标记为@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 Language Documentation

  

如果您的协议标有@objc属性,则只能指定可选的协议要求。

     

...

     

另请注意,@ objc协议只能由类采用,而不能   通过结构或枚举。如果您将协议标记为@objc in   为了指定可选要求,您将只能申请   类协议的类协议。

答案 1 :(得分:1)

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

在声明上使用@objc告诉编译器将它暴露给Objective-C运行时。为了使其成为可能,声明为@objc的类型必须能够在Objective-C中表示。

对于类,这意味着它们必须从NSObject继承。对于方法,这意味着它们由动态Objective-C消息传递支持。

答案 2 :(得分:1)

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

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

非私人班级的警告不太可能上升。

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

两者都很好。

答案 3 :(得分:0)

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

    public protocol Speaker {
      func Speak()
      func TellJoke()
    }

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

奖金是你不会继承所有物品行李。