En Swift, veo algunos métodos como:
@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
Me preguntaba, ¿cuándo usar @objc? Leí algunos documentos, pero dicen que cuando desee que se pueda llamar en Objective-C, debe agregar la bandera @objc
Sin embargo, esta es una función privada en Swift, ¿qué hace @obj?
Respuestas:
privado significa que solo es visible en Swift. así que use @objc para ser visible en Objective-C. Si tiene una función para seleccionar una función privada en rápido, es necesaria.
Ver: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html
fuente
@objc private func doubleTapGestureRecognized
, cuál es el punto de tener tanto @objc y privada? ¿Estás diciendo que las clases de Objective-C pueden sobrescribir doubleTapGestureRecognized?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 unprivate
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 elDistributedNotification
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 controladoreswillSet
y la propiedad privadadidSet
. Además, la propiedad estática que informa al sistema KVC del quedependentProperty
dependeoriginalProperty
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.
fuente
@objc / dinámico
Es por compatibilidad: una vez que importe su archivo / código Swift en un proyecto basado en Objective-C.
Y utilícelo si desea que el código o la clase de Objective-C acceda a su propiedad / método.
La mayoría de las veces sucede cuando está subclasificando una clase Swift de la clase base Objective-C.
Aquí la documentación de Apple que dice sobre
@objc
.Usando Swift desde Objective-C
Compatibilidad de interoperabilidad de idiomas
Enlaces actualizados:
parece que Apple ha actualizado los enlaces.
fuente
@objc es un atributo de clase, por lo que usa
@objc public class MyClass
Expone los métodos de la clase a las clases de Objective C, por lo que solo lo usará si su clase contiene funciones públicas
fuente
Una respuesta tardía, pero este
@objc
comportamiento está cambiando ligeramente a partir de Swift 4 (que salió en Xcode 9, que generalmente se lanzó hace 10 días).En Swift 4,
@objc
se eliminan algunos casos de inferencia de . Esto solo significa que en algunos casos adicionales en los que antes de que el@objc
compilador de Swift infiera el encabezado, no se infiere en Swift 4.Leer más en la propuesta de evolución Swift sobre este cambio
Como se ha mencionado, en general se
@objc
trata de exponer ciertos métodos al tiempo de ejecución de Objective-C, que es parte de la interoperabilidad de Swift con el lenguaje.fuente
@objc
@objc
expone una declaración aObjective-C runtime
. Echemos un vistazo a la#selector
función de Swift para usar un tiempo de ejecución de Objective-C. En este caso, puede definir su Swift@objc private func
[Más]Para usar las funciones de Swift de Objective-C:
NSObject
De Mark Swift:
a. solo
@objcMembers
clase : para exponer todos lospublic
constructores , campos y métodos . También es aplicable para subclases.segundo.
@objc
clase / enumeración / protocolo (excepto estructura ) [Tipo con nombre]@objc
class (opcional): para exponer un archivopublic init()
. O@objc(<custom_name>)
para configurar un nombre personalizado para la clase.@objc
constructores , campos y métodos - para exponerlos selectivamenteEl método de Swift estará disponible con el siguiente nombre:
<swiftName>With<firstArgument>:<secondArgument>:
Por ejemplo:
public func printHelloWorld(arg1: String, arg2:String) //is reached through: [someObject printHelloWorldWithArg1: arg2:];
[
@objc
ydynamic
]fuente