Another late answer, but none of the existing answers on this question really answer the OP's question, which is: why the heck would you need to use @objc
on a private
class member, if @objc
is there for interaction with Objective-C, and the member in question is private, meaning that even if you have Objective-C code in your project, it shouldn't be able to see the member anyway?
The reason is that, because many of the frameworks are written in Objective-C, sometimes Objective-C features are needed to interact with certain APIs.
For example, suppose I want to register for a notification via DistributedNotificationCenter
:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
For this to work, we need to be able to get the selector for the somethingHappened
method. However, selectors are an Objective-C concept, so if the method is not visible to Objective-C, it does not have a selector. Therefore, even if the method is private and should not be called by arbitrary outside code, it will need an @objc
in order for the DistributedNotification
code, which is written in Objective-C, to be able to call it via its selector.
Another common case where @objc
is needed is to support Key-Value Coding (KVC), especially on macOS, where KVC and KVO are used to implement Cocoa Bindings. KVC is, like many other systems in Cocoa, implemented in Objective-C, which has the effect of requiring KVC-compliant properties to be exposed to the Objective-C runtime. Sometimes, it makes sense for KVC-compliant properties to be private. One example is when you have a property that affects other properties:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
In this case, our actual stored property is private, but the dependent property, which we do expose to outside code, needs to send its notifications when the private property is updated. By marking the private property as @objc
, we can easily do that by setting up a KVC dependency—otherwise, we'd have to write code to manually send the notifications in the private property's willSet
and didSet
handlers. In addition, the static property that informs the KVC system that dependentProperty
is dependent on originalProperty
needs to be exposed to Objective-C so that the KVC system and find it and call it, but it's not relevant to clients of our code.
Also, a view controller in a macOS app that updates controls in its view using Cocoa Bindings as an implementation detail may make certain private properties KVC-compliant in order to bind those controls to them.
So as you see, there are times when a method or property may need to be exposed to Objective-C in order to interact with the frameworks, without necessarily needing to be visible to clients of your code.