简体   繁体   English

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

[英]Candidate is not '@objc' but protocol requires it

I have been following this tutorial to learn swift & iOS app development. 我一直在学习这个教程,以学习swift和iOS应用程序开发。 In the Protocol section, the tutorial defined the following protocol: 在Protocol部分,本教程定义了以下协议:

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

It says If you want to have a protocol with optional methods, you must prefix the protocol with the @objc tag (even if your class is not interoperating with objective-C) . 它说如果你想拥有一个带有可选方法的协议,你必须在协议前加上@objc标签(即使你的类没有与objective-C互操作)

Then, it shows the sample to implement the protocol: 然后,它显示了实现协议的示例:

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

I tried the above code in my xcode playground, but I got the compiler error "Type Vicki doesn't conform to protocol Speaker" . 我在我的xcode playground中尝试了上面的代码,但是我得到了编译错误“Type Vicki不符合协议Speaker”

Xcode also pops up an fix-it text which says "Candidate is not '@objc' but protocol requires it" . Xcode还弹出一个修复文本,上面写着“候选人不是'@objc',但协议需要它”

I get completely confused now, the tutorial doesn't mention this error at all. 我现在感到很困惑,教程根本没有提到这个错误。 Could someone please explain to me all this to make me clear? 有人可以向我解释这一切让我明白吗? Thanks! 谢谢!

From what I can tell, marking your protocol as @objc means that any classes implementing it also have to be exposed to Objective-C. 据我所知,将协议标记为@objc意味着任何实现它的类也必须暴露给Objective-C。 This can be done either by making Vicki a subclass of NSObject: 这可以通过使Vicki成为NSObject的子类来完成:

class Vicki: NSObject, Speaker {

Or by marking each implemented method as @objc: 或者将每个实现的方法标记为@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?")
    }
}

Update: From Apple's Swift Language Documentation 更新:来自Apple的Swift语言文档

Optional protocol requirements can only be specified if your protocol is marked with the @objc attribute. 只有在协议标记为@objc属性时,才能指定可选的协议要求。

... ...

Note also that @objc protocols can be adopted only by classes, and not by structures or enumerations. 另请注意,@ objc协议只能由类采用,而不能由结构或枚举采用。 If you mark your protocol as @objc in order to specify optional requirements, you will only be able to apply that protocol to class types. 如果将协议标记为@objc以指定可选要求,则只能将该协议应用于类类型。

In order for a type to conform to a protocol marked @objc , that type must also marked with @objc or the methods being used to satisfy the protocol must be. 为了使类型符合标记为@objc的协议,该类型还必须用@objc标记,或者用于满足协议的方法必须是。

Using @objc on a declaration tells the compiler to expose it to the Objective-C runtime. 在声明上使用@objc告诉编译器将它暴露给Objective-C运行时。 In order for that to be possible, the type that was declared @objc must be able to be represented in Objective-C. 为了使其成为可能,声明为@objc的类型必须能够在Objective-C中表示。

For classes this means they must inherit from NSObject. 对于类,这意味着它们必须从NSObject继承。 For methods, this means they become backed by dynamic Objective-C message passing. 对于方法,这意味着它们由动态Objective-C消息传递支持。

Looks like we only need to prefix protocol method with @objc in private class. 看起来我们只需要在私有类中使用@objc作为协议方法的前缀。

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

Warning is not likely to rise for non-private class. 非私人班级的警告不太可能上升。

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

Both are fine. 两者都很好。

Add an extension to the protocol returning empty functions and default values. 为协议添加一个扩展,返回空函数和默认值。 Any class that conforms to the protocol and wishes to override any func or var may optionally do so. 任何符合协议并希望覆盖任何func或var的类都可以选择这样做。

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

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

The bonuses are you don't inherit all of the obj-c baggage. 奖金是你不继承所有的物品行李。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM