Optional can only be applied to @objc protocol members

Here I define the protocol in Swift:

protocol DrawViewProtocol : class{ optional func drawViewDidEndEditing() // Warning! } 

And the compiler gave me an error.

Optional can only be applied to @objc protocol members

So, I understand that optional and required are only available in Objective-C? Although, how to define optional or required in pure Swift style?

+5
source share
6 answers

Swift does not allow protocols to have optional requirements - if the protocol declares something, it is necessary. Objective-C has long been aware of additional requirements, and Swift recognizes this when you use @objc when declaring a protocol. So using @objc is an easy way to get what you need.

If you want a clean Swift solution, you need to add a protocol extension that includes standard method implementations. This does not make these methods optional; instead, he says that any class that does not implement the method itself will use the default implementation instead. They are optional in these classes, they do not need to implement them, but not very optionally, because this happens only because the default implementation is available.

It will look something like this:

 protocol DrawViewProtocol : class{ func drawViewDidEndEditing() } extension DrawViewProtocol { func drawViewDidEndEditing() {} } class MyClass : DrawViewProtocol { } class MyOtherClass : DrawViewProtocol { func drawViewDidEndEditing() { print("Foo") } } 

Now, if I create an instance of MyClass and call drawViewDidEndEditing() , it uses the default implementation, which does nothing. If I create an instance of MyOtherClass , the same method will print "Foo".

+24
source

In Swift 3 and Swift 4, use @objc for an optional prototype

 @objc protocol YourProtocolName: class { @objc optional func yourMethodName() } 
+9
source

From the apple documentation: Even if you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you want to specify optional requirements.

See the Optional Protocol Requirements section of this document.

+2
source

You can do it as follows:

 @objc protocol MyProtocol { optional func myMethod() } 
+1
source

Although the answers above are indeed correct, they do not provide you with a clean-fast answer.

The correct way to do this in Swift is to actually use protocols:

  • Define your first protocol, A, only with the necessary properties, methods, ... you name it
  • Define a second protocol B with your so-called "optional" properties.
  • Therefore, all your classes / protocols that should be A-compatible will be.
  • Those that require "optional" compliance can be expanded using protocol B compliance.

Example:

 protocol MyRequiredProtocol { var a: String { get } var b: String { get } func aMethod() } protocol MySoCalledOptionalProtocol { var c: String { get } func anotherMethod() } class MyFirstClass: MyRequiredProtocol { var a: String { return "a" } var b: String { return "b" } func aMethod() { // Do something } } class MySecondClass: MyRequiredProtocol, MySoCalledOptionalProtocol { var a: String { return "a" } var b: String { return "b" } var c: String { return "c" } func aMethod() { // Do something } func anotherMethod() { // Do something } } 
+1
source

Just add @objc before the protocol as follows:

 @objc protocol FriendsTableDelegate { func didSelectFriend(friend: User) -> Void optional func didSelectFriend(friend: User, cell: FriendCell) -> Void } 
+1
source

All Articles