Greetings, traveler!
You may have heard about marker protocols. They used to mark entities without providing any requirements. But did you know Swift has a specific underscore attribute for such protocols? I am talking about the @_marker
attribute.
Note
There is a warning in Swift documentation about underscore attributes:
Usage of these attributes outside of the Swift monorepo is STRONGLY DISCOURAGED.
The semantics of these attributes are subject to change and most likely need to go through the Swift evolution process before being stabilized.
All the stable attributes are described here.
The only example in Swift we can find is the Sendable
protocol, which basically does only one thing — separate the wheat from the chaff.
Note
By the way, if you want to read more about Sendable
and @Sendable
closures, you can do so here.
So, we can do the same thing. Checkout this example:
@_marker protocol ThreadSafeProtocol {}
class Object: ThreadSafeProtocol {}
func doSomething(with object: ThreadSafeProtocol) {
DispatchQueue.global().async {
// do something
}
DispatchQueue.global().async {
// do something
}
}
let object = Object()
doSomething(with: object)
But this is a really only marker protocol. So, you can’t add any requirements.
@_marker protocol ThreadSafeProtocol {
var isTrue: Bool { get set } // ❌ Error
}
❌ Marker protocol ‘ThreadSafeProtocol’ cannot have any requirements
Also, you can’t use casting with such protocols. That means you can’t do something like that:
@_marker protocol MarkerProtocol {}
class A: UIView {}
class B: UIView {}
extension A: MarkerProtocol {}
let array = [A(), B()]
array.filter { ($0 as? MarkerProtocol) != nil } // ❌ Error
❌ Marker protocol ‘MarkerProtocol’ cannot be used in a conditional cast
Conclusion
There isn’t a significant chance of encountering a situation where this attribute will be a lifesaver. Moreover, it is not recommended to use it before becoming stable.
If you enjoyed this article, please feel free to follow me on my social media: