Optional Protocols in Swift
Hey there fellow Swift enthusiast! Today we’re going to delve into the fascinating world of optional protocols in Swift and take a closer look at the @objc attribute.
Optional Protocol
First, let’s define what an optional protocol is. In Swift, a protocol is essentially a blueprint that defines a set of methods, properties, and other requirements that a conforming type must implement. However, sometimes you may want to define a protocol where some of its requirements are optional. This is where optional protocols come in handy.
To declare an optional protocol, simply add the optional keyword before the requirement, like so:
@objc protocol MyOptionalProtocol {
@objc optional func optionalMethod()
func requiredMethod()
}Here, we’ve defined a protocol called MyOptionalProtocol with two requirements: optionalMethod() and requiredMethod(). However, we've marked optionalMethod() with the @objc optional attribute, indicating that it's an optional requirement.
@objc
Now, you may be wondering why we need the @objc attribute in conjunction with optional protocols. The reason is that Swift's optional protocols are actually built on top of Objective-C's runtime system. By marking the protocol with the @objc attribute, we're essentially telling the compiler to generate the necessary Objective-C runtime metadata to support the optional requirement.
Without the @objc attribute, the optional requirement wouldn't be recognized by the Objective-C runtime, and attempting to call it would result in a runtime error. So, it's important to always use the @objc attribute when defining optional protocols in Swift.
Get Ario Liyan’s stories in your inbox
Join Medium for free to get updates from this writer.
One thing to keep in mind is that the @objc attribute also has some other implications, such as making the protocol compatible with Objective-C code and potentially impacting performance. So, it's important to use it judiciously and only when necessary.
Optional protocols’ functions’ arguments
When defining a function in an optional protocol, it’s important to keep in mind that the function arguments must be representable in Objective-C. For example, let’s say we have an optional protocol with the following function:
struct Object{
let name: String
}
@objc protocol MyOptionalProtocol {
@objc optional func optionalFunction(with object: Object)
}Here, we’ve defined an optional function called optionalFunction that takes an Object type as an argument. However, the Object type is not representable in Objective-C. This means that attempting to call this function from Objective-C code would result in a compile-time error.
It’s important to note that this requirement only applies to function arguments in optional protocols. In regular protocols, Swift types like our Object are perfectly fine to use as function arguments.
Fix for “Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C”
The error message we’re seeing — “Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C” — is indicating that the Object type used as a parameter in our optionalFunction method cannot be represented in Objective-C.
To solve this issue, we can change the Object type to a type that can be represented in Objective-C, such as NSString or NSNumber. Alternatively, we can create a new Objective-C-compatible wrapper class for the Object type and use that as the parameter type.
Here’s an example of how we could modify your code to use an NSString parameter:
struct Object {
let name: String
}
@objc class ObjectWrapper: NSObject {
let object: Object
init(object: Object) {
self.object = object
}
}
@objc protocol MyOptionalProtocol {
@objc optional func optionalFunction(with object: ObjectWrapper)
}In this modified code, we’ve created a new ObjectWrapper class that wraps the Object type. We've also changed the parameter type of the optionalFunction method to be an ObjectWrapper instance.
Now, when we call the optionalFunction method from Objective-C code, we can pass in an ObjectWrapper instance instead of an Object instance
Conclusion
In conclusion, optional protocols are a powerful feature in Swift that allow us to define protocols with optional requirements. When using optional protocols, it’s important to always mark them with the @objc attribute to ensure that they're recognized by the Objective-C runtime system. Happy coding!










