The Swift documentation says the following about protocols:
You can check for protocol conformance only if your protocol is marked with the @objc attribute, as seen for the HasArea protocol above. This attribute indicates that the protocol should be exposed to Objective-C code and is described in Using Swift with Cocoa and Objective-C. Even if you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you want to be able to check for protocol conformance.
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 check for conformance, you will be able to apply that protocol only to class types.
and
Optional protocol requirements can only be specified if your protocol is marked with the @objc attribute. 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.
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.
Why cannot pure Swift protocols (non-@objc
) be checked for conformance. Why don't they have optional requirements? Can anybody guess the underlying language design reason?
I expect that at some undetermined (probably far away) time in the future Apple will slowly reimplement and replace Cocoa and CocoaTouch with libraries programmed purely in Swift. At that time, if we wan't to avoid using any Obj-C related stuff, should we avoid using optional protocol requirements and protocol checks conformance in our code?
If so, what's Swift's idiomatic way of achieving similar patterns without using @objc
? (E.g., a delegate with optional methods.)
For example, this simple use case cannot be implemented with non-@objc
protocols (and Printable
, DebugPrintable
and Streamable
are non-@objc
:
import UIKit
let firstName = "John"
let lastName = "Appleseed"
let age = 33
let height = 1.74
let values: [Any] = [firstName, lastName, age, height]
let stringifiedValues = [String]()
for value in values
{
if let pritanbleValue = value as? Printable
{
stringifiedValues.append(value.description)
}
else if let debugPrintableValue = value as? DebugPrintable
{
stringifiedValues.append(value.debugDescription)
}
else if let streamableValue = value as? Streamable
{
var string = ""
streamableValue.writeTo(&string)
stringifiedValues.append(string)
}
// etc.
else
{
stringifiedValues.append("[NoStringRepresentation]")
}
}
jckarter, an Apple employee, said the following on an Apple Developer Forums' thread: