¿Cómo usar los selectores Swift 3?

Hasta ahora he tenido este código

if UIScreen.instancesRespondToSelector(Selector("scale")) { UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale); }else{...} 

No escribí este código, así que no estoy seguro de para qué UIScreen.mainScreen() , pero parece que querían verificar que UIScreen.mainScreen() de hecho, puede tener la variable .scale (?).

Al mirar el .scale , me parece que está disponible desde iOS 4.0. Dado que soportamos hasta iOS 7, esto no debería ser necesario, ¿verdad?

De todos modos, este no es el problema actual. Ahora tengo cientos de advertencias debido a Xcode 7.3 hacia Swift 3 con estas nuevas instantáneas de selector o cualquier otra cosa.

Xcode quiere que cambie esto:

Selector("scale")

dentro

#selector(NSDecimalNumberBehaviors.scale)

Hasta ahora, todos los otros selectores que he cambiado han sido lógicos, como "cambiar Selector("hello") a #selector(MyClass.hello) , pero este NSDecimal.. suena un poco drástico. ¿Puedo confiar en que Xcode selecciona el selector correcto ? No puedo encontrar NSDecimalNumberBehaviors cualquier lugar conectado a UIScreen.scale .. Si #selector(UIScreen.scale) obtengo un error ..

Lo único que sé con certeza es que si tengo CMD + click la scale aquí: NSDecimalNumberBehaviors.scale y aquí: UIScreen.mainScreen().scale termino en diferentes lugares …

Como se señaló en los comentarios, este código es un vestigio remanente de bashs de soportar versiones antiguas de iOS que no solo ya no son relevantes, sino que incluso no se pueden orientar cuando se desarrollan en Swift.

Simplemente llame a UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale) directamente: la propiedad de scale existe en todas las versiones de iOS que puede orientar con Swift, por lo que no hay necesidad de comprobarlo.

De hecho, en general, no es una buena idea probar la disponibilidad de la API utilizando verificaciones selectoras. Es posible que exista un selector en una versión inferior a la que está segmentando, pero que sea API privada con diferente comportamiento, por lo que su verificación tendrá éxito, pero su código no se comportará correctamente. Es por eso que el sistema @available y #available se introdujo en Swift 2.

(Otra ventaja de la comprobación de la disponibilidad basada en la versión: cuando una versión del sistema operativo tiene la edad suficiente para que pueda eliminar el soporte, es mucho más fácil encontrar todos los sitios en su código que pueda limpiar. No tiene que recordar qué versión método / propiedad se hizo universal en).


Si por alguna otra razón necesita formar un Selector para UIScreen.scale … no puede usar la expresión #selector para hacer eso en Swift 2.2, porque la scale es una propiedad, no un método. En Swift 2.2, #selector toma una function / reference, y no hay forma de get una reference al método getter o setter subyacente de una propiedad. Aún necesitarías build ese selector a partir de una cadena. Para evitar la advertencia, oculte el literal de cadena de forma temporal:

 let scale = "scale" let selector = Selector(scale) 

O haga otra danza que pase una cadena, pero no pase directamente una cadena literal , al inicializador Selector :

 let selector = Selector({"scale"}()) 

En Swift 3 habrá una forma especial de #selector para properties getters / setters , pero aún no ha aterrizado.

Mis dos centavos:

  • 1) swift tiene un nuevo sntax para selectores
  • 2) el comstackdor puede detectar methods de manera segura en function de:
    • norte. de params
    • tipo de cada param
    • tipo de resultado (SÓLO de forma rápida, así que olvidémoslo ahora)

veamos 4 casos:

UN)

 .. closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside) } func doIt(_ sender: UIButton) { print("touched") } func doIt() { print("touched2 ") } 

El uso ambiguo de 'doIt'

SEGUNDO)

 closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside) } // func doIt(_ sender: UIButton) { // print("touched") // } func doIt() { print("touched2 ") } 

funciona, ya que el comstackdor puede detectar el ÚNICO método que puede coincidir con la firma

DO)

 closeBtn.addTarget(self, action: #selector(doIt(_:)), for: .touchUpInside) } func doIt(_ sender: UIButton) { print("touched") } func doIt() { print("touched2 ") } 

funciona, ya que el comstackdor puede detectar el ÚNICO método que puede coincidir con la firma.

RE)

 closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside) } func doIt(_ sender: UIButton) { print("touched") } /* func doIt() { print("touched2 ") } */ 

funciona y:

  • El comstackdor puede detectar el ÚNICO método que puede coincidir con el
    firma
  • en el depurador También obtendrá la reference de button correcta, ya que el CÓDIGO de UIB (en iOS libs) presiona la dirección del button en el
    stack, ya que el comstackdor crea un marco de stack.