Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Candidate is not '@objc' but protocol requires it

Tags:

xcode

ios

swift

I have been following this tutorial to learn swift & iOS app development. In the Protocol section, the tutorial defined the following 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).

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 also pops up an fix-it text which says "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!

like image 227
Leem.fin Avatar asked Aug 11 '15 12:08

Leem.fin


People also ask

What is a protocol OBJC?

Protocols are used in Objective-C to declare a set of methods and properties for a class to implement. They have a similar purpose to ABCs (abstract base classes) in Python.

What does @objc do in Swift?

@objc means you want your Swift code (class, method, property, etc.) to be visible from Objective-C. dynamic means you want to use Objective-C dynamic dispatch.


2 Answers

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:

class Vicki: NSObject, Speaker {

Or by marking each implemented method as @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

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.

like image 165
Tom Elliott Avatar answered Sep 27 '22 22:09

Tom Elliott


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.

Using @objc on 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 @objc must be able to be represented in Objective-C.

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

like image 27
waltflanagan Avatar answered Sep 27 '22 22:09

waltflanagan