xcode 候选人不是“@objc”,但协议要求它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31941771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 07:39:39  来源:igfitidea点击:

Candidate is not '@objc' but protocol requires it

iosxcodeswift

提问by Leem.fin

I have been following this tutorialto learn swift & iOS app development. In the Protocol section, the tutorial defined the following protocol:

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

@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 不符合协议扬声器”

Xcode also pops up an fix-ittext which says "Candidate is not '@objc' but protocol requires it".

Xcode 还会弹出一个修复文本,上面写着“Candidate is not '@objc' but protocol requires it”

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!

我现在完全糊涂了,教程根本没有提到这个错误。有人可以向我解释这一切以使我清楚吗?谢谢!

采纳答案by Tom Elliott

From what I can tell, marking your protocol as @objc means that any classes implementing it also have to be exposed to Objective-C. This can be done either by making Vicki a subclass of NSObject:

据我所知,将您的协议标记为 @objc 意味着任何实现它的类也必须暴露给 Objective-C。这可以通过使 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.

...

Note also that @objc protocols can be adopted only by classes, and not by structures or enumerations. 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 属性标记时才能指定。

...

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

回答by waltflanagan

In order for a type to conform to a protocol marked @objc, that type must also marked with @objcor the methods being used to satisfy the protocol must be.

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

Using @objcon a declaration tells the compiler to expose it to the Objective-C runtime. In order for that to be possible, the type that was declared @objcmust be able to be represented in Objective-C.

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

For classes this means they must inherit from NSObject. For methods, this means they become backed by dynamic Objective-C message passing.

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

回答by Medo Paw

Looks like we only need to prefix protocol method with @objcin 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.

两者都很好。

回答by Chris

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 optionallydo 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.

好处是你不会继承所有的 obj-c 包袱。