Otra respuesta tardía, pero ninguna de las respuestas existentes en esta pregunta realmente responde a la pregunta del OP, que es: ¿por qué diablos necesitaría usarla @objc
en un private
miembro de la clase, si @objc
está allí para interactuar con Objective-C y el miembro en cuestión? es privado, lo que significa que incluso si tiene código Objective-C en su proyecto, ¿no debería poder ver al miembro de todos modos?
La razón es que, debido a que muchos de los marcos están escritos en Objective-C, a veces se necesitan características de Objective-C para interactuar con ciertas API.
Por ejemplo, supongamos que quiero registrarme para recibir una notificación a través de DistributedNotificationCenter
:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
Para que esto funcione, necesitamos poder obtener el selector para el somethingHappened
método. Sin embargo, los selectores son un concepto de Objective-C, por lo que si el método no es visible para Objective-C, no tiene selector. Por lo tanto, incluso si el método es privado y no debe ser llamado por código externo arbitrario, necesitará un @objc
orden para que el DistributedNotification
código, que está escrito en Objective-C, pueda llamarlo a través de su selector.
Otro caso común en el que @objc
se necesita es admitir la codificación de valores clave (KVC), especialmente en macOS, donde se utilizan KVC y KVO para implementar Cocoa Bindings. KVC, como muchos otros sistemas en Cocoa, está implementado en Objective-C, lo que tiene el efecto de requerir que las propiedades compatibles con KVC estén expuestas al tiempo de ejecución de Objective-C. A veces, tiene sentido que las propiedades compatibles con KVC sean privadas. Un ejemplo es cuando tiene una propiedad que afecta a otras propiedades:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
En este caso, nuestra propiedad almacenada real es privada, pero la propiedad dependiente, que sí exponemos en el código externo, tiene que enviar sus notificaciones cuando la propiedad privada se actualiza. Al marcar la propiedad privada como @objc
, podemos hacerlo fácilmente configurando una dependencia de KVC; de lo contrario, tendríamos que escribir código para enviar manualmente las notificaciones en los controladores willSet
y la propiedad privada didSet
. Además, la propiedad estática que informa al sistema KVC del que dependentProperty
depende originalProperty
debe estar expuesta a Objective-C para que el sistema KVC lo encuentre y lo llame, pero no es relevante para los clientes de nuestro código.
Además, un controlador de vista en una aplicación macOS que actualiza los controles en su vista usando Cocoa Bindings como un detalle de implementación puede hacer que ciertas propiedades privadas sean compatibles con KVC para vincular esos controles a ellos.
Entonces, como puede ver, hay ocasiones en las que un método o propiedad puede necesitar exponerse a Objective-C para interactuar con los marcos, sin necesariamente tener que ser visible para los clientes de su código.