Yesterday I was watching a talk from Nikita Lutsenko about Swift and Objective-C Interoperability. At some point he states:
What Objective-C protocols are in Swift is very special. There is so much that was added specifically for it. It’s also weaker and not Swift-y, even though you can use optional. So, optional is not supported on Swift protocols, unless they are exported into Objective-C, because that time, they become Objective-C protocols.
There is also no ability to talk to extensions of these protocols. Either they are concrete extensions, with no way you can talk to a protocol and build things like protocol extensions, which we all love and use in Swift. So they’re very limited altogether.
If you actually are writing Swift code, please don’t use these, they make everyone’s life bad as well as they could not be used, say, in a Linux environment, where you don’t have Objective-C runtime.
He’s right! When you annotate a protocol with @objc, LLVM will generate a bunch of extra things: an isa pointer, runtime sections like: __objc_imageinfo, __objc_classref, etc. It seems that it’s casting the protocol into a NSObject, and maybe it will have a performance penalty. Also @objc protocols can not be used with struct and enums, just class types.
So, let’s think this thoroughly, shall we?
optional means that a function may or may not exist.
In Objective-C, before passing a message, we have to check for respondsToSelector, otherwise it will crash at runtime.
In Swift, we just call the function, followed by a ?, all safe, no crashes.
But I think that there’s a more Swifty way of doing that, by using protocol extensions, take a look:
Now, if someone calls optionalMethodOne(), nothing happens, due to it’s empty implementation. We also mitigate the risk of someone, accidentally, forcing unwrap an optional functional. Not to mention the fact that, now, it’s not constraint to a specific type!