selector() swift 4
¿Cómo puedo lidiar con la deprecación de inferencia @objc con#selector() en Swift 4? (5)
A partir de, creo que Swift 4.2, todo lo que necesitas hacer es asignar @IBAction a tu método y puedes evitar esta tonta anotación @objc
`` `
let tap = UITapGestureRecognizer(target: self, action: #selector(self.cancel))
@IBAction func cancel()
{
self.dismiss(animated: true, completion: nil)
}
Estoy tratando de convertir el código fuente de mi proyecto de Swift 3 a Swift 4. Una advertencia que me da Xcode es sobre mis selectores.
Por ejemplo, agrego un objetivo a un botón usando un selector regular como este:
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
Esta es la advertencia que muestra:
El argumento de ''#selector'' se refiere al método de instancia ''myAction ()'' en ''ViewController'' que depende de la inferencia de atributo ''@objc'' en desuso en Swift 4
Agregue ''@objc'' para exponer este método de instancia a Objective-C
Ahora, presionar
Fix
en el mensaje de error hace esto a mi función:
// before
func myAction() { /* ... */ }
// after
@objc func myAction() { /* ... */ }
Realmente no quiero cambiar el nombre de todas mis funciones para incluir la marca
@objc
y supongo que no es necesario.
¿Cómo reescribo el selector para lidiar con la desaprobación?
Pregunta relacionada:
Como ya se mencionó en otras respuestas, no hay forma de evitar la anotación
@objc
para los selectores.
Pero la advertencia mencionada en el OP se puede silenciar siguiendo los siguientes pasos:
- Ir a la configuración de compilación
- Buscar la palabra clave @objc
-
Establezca el valor de la
interfaz Swift 3 @objc
en
Off
a continuación se muestra la captura de pantalla que ilustra los pasos mencionados anteriormente:
Espero que esto ayude
La solución es correcta: no hay nada sobre el selector que pueda cambiar para que el método al que hace referencia esté expuesto a Objective-C.
La razón de esta advertencia en primer lugar es el resultado de
SE-0160
.
Antes de Swift 4, se infirió que los miembros
internal
o superiores compatibles con Objective-C de las clases
NSObject
de
NSObject
eran
@objc
y, por lo tanto, se exponían a Objective-C, por lo que se les podía llamar utilizando selectores (ya que el tiempo de ejecución Obj-C se requiere para para buscar la implementación del método para un selector dado).
Sin embargo, en Swift 4, este ya no es el caso.
Ahora solo se infiere que las declaraciones muy específicas son
@objc
, por ejemplo, anulaciones de los métodos
@objc
, implementaciones de los requisitos del protocolo
@objc
y declaraciones con atributos que implican
@objc
, como
@IBOutlet
.
La motivación detrás de esto, como se detalla
SE-0160
, es en primer lugar evitar que las sobrecargas de métodos en las clases
NSObject
de
NSObject
entre sí debido a que tienen selectores idénticos.
En segundo lugar, ayuda a reducir el tamaño binario al no tener que generar thunks para los miembros que no necesitan estar expuestos a Obj-C, y en tercer lugar mejora la velocidad de la vinculación dinámica.
Si desea exponer a un miembro a Obj-C, debe marcarlo como
@objc
, por ejemplo:
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(foo), for: .touchUpInside)
}
@objc func foo() {
// ...
}
}
(el migrador debe hacer esto automáticamente por usted con los selectores cuando se ejecuta con la opción "minimizar inferencia" seleccionada)
Para exponer un grupo de miembros a Obj-C, puede usar una
@objc extension
:
@objc extension ViewController {
// both exposed to Obj-C
func foo() {}
func bar() {}
}
Esto expondrá todos los miembros definidos en él a Obj-C, y dará un error en cualquier miembro que no pueda exponerse a Obj-C (a menos que se marque explícitamente como
@nonobjc
).
Si tiene una clase donde necesita que
todos los
miembros compatibles con Obj-C estén expuestos a Obj-C, puede marcar la clase como
@objcMembers
:
@objcMembers
class ViewController: UIViewController {
// ...
}
Ahora, todos los miembros que se pueden inferir que son
@objc
serán.
Sin embargo, no recomendaría hacer esto a menos que
realmente
necesite que todos los miembros estén expuestos a Obj-C, dadas las desventajas mencionadas anteriormente de tener miembros expuestos innecesariamente.
Si necesita miembros objetivos c en su controlador de vista, simplemente agregue @objcMembers en la parte superior del controlador de vista. Y puede evitar esto agregando IBAction en su código.
@IBAction func buttonAction() {
}
Asegúrese de conectar esta salida en el guión gráfico.
Como documentación oficial de Apple . necesitas usar @objc para llamar a tu Método Selector.
En Objective-C, un selector es un tipo que se refiere al nombre de un método Objective-C. En Swift, los selectores Objective-C están representados por la estructura
Selector
, y se pueden construir utilizando la expresión#selector
. Para crear un selector para un método que se pueda llamar desde Objective-C, pase el nombre del método, como#selector(MyViewController.tappedButton(sender:))
. Para construir un selector para el método getter o setter Objective-C de una propiedad, pase el nombre de la propiedad con el prefijogetter:
osetter:
label, como#selector(getter: MyViewController.myButton)
.