swift - mac - "Classname no tiene nombre de función miembro" al agregar UIButton target
swift for mac download (4)
Esto sucedió porque Swift 3 ha cambiado la forma en que maneja el primer nombre del parámetro. En Swift 3 , todos los nombres de los parámetros se deben usar cuando se llama a una función a menos que se haya declarado un _
explícito como el nombre del parámetro.
Lo que usaste como selector fue correcto si declaraste tu función como:
func ratingButtonTapped(_ button: AnyObject) {
print("Button pressed 👍")
}
También podría haber usado esto como su selector:
#selector(RatingControl.ratingButtonTapped(button:))
Se agregó @objc a la definición de clase según esta respuesta (pero eso parece extraño solo para Swift, ¿no?)
Su código puede estar en Swift, pero está interactuando con el tiempo de ejecución de Objective-C cuando está codificando Cocoa Touch (marco de iOS). El selector es una función que debe estar visible para el tiempo de ejecución de Objective-C. NSObject
esto de forma gratuita la mayor parte del tiempo porque estás implementando esto en una clase que finalmente hereda de NSObject
(como UIViewController
). Si tiene una clase exclusiva de Swift que no hereda de NSObject
, puede agregar @objc
para hacer que la clase y los métodos sean visibles para el tiempo de ejecución de Objective-C.
Super newb en Swift y desarrollo de iOS aquí.
Estoy siguiendo este tutorial sobre la implementación de un control personalizado en una aplicación iOS de vista única. Es un tutorial de Swift 2, pero hasta ahora estoy haciendo bien en transponer todo a 3 a medida que avanzo (uso XCode 8 Beta).
Tengo una clase personalizada, RatingControl
, conectada a una View
en el guión gráfico.
En el constructor de la clase, creo un botón:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.red()
Luego, intento asignar una acción al botón. El tutorial dice que debería hacerlo así:
button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(_:)),
for: .touchDown)
y luego crea, en la misma clase RatingControl
, el método:
func ratingButtonTapped(button: UIButton) {
print("Button pressed 👍")
}
Pero cuando compilo, se queja:
tipo "RatingControl" no tiene ningún miembro "ratingButtonTapped"
He asegurado al 100% que la función está ahí, en la clase y con el nombre correcto. Fuente completa
¿Hay algo obvio que me estoy perdiendo?
Lo que probé:
Se agregó
@objc
a la definición de clase según esta respuesta (pero eso parece extraño solo para Swift, ¿no?)Hecho que
ratingButtonTapped()
explícitamentepublic
(pero eso no parece que debería ser necesario)Jugueteó con cadenas en lugar de selectores,
button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)
y muchos más, pero eso simplemente falla más adelante.
En Swift 3, la referencia de método para: func ratingButtonTapped(button: UIButton)
convierte en ratingButtonTapped(button:)
.
Entonces, usar #selector(RatingControl.ratingButtonTapped(button:))
también funciona.
Y si desea mantener #selector(RatingControl.ratingButtonTapped(_:))
, debe declarar el método ratingButtonTapped
como:
func ratingButtonTapped(_ button: UIButton) { //<- `_`
print("Button pressed 👍")
}
Y si solo tiene un método de ratingButtonTapped
en la clase, puede dirigirse al selector como #selector(RatingControl.ratingButtonTapped)
o simplemente (desde dentro de la clase #selector(ratingButtonTapped)
) #selector(ratingButtonTapped)
.
Si desea llamar a una acción que está en su Controlador de Vista desde una Clase Diferente, puede intentar esto.
Use ViewController () para su objetivo. Use ViewController.functionName para su selector. No use un método auxiliar para la variable del controlador de vista como "vc"; de lo contrario, no podrá acceder a objetos dentro de ViewController.
Aquí hay un objetivo de ejemplo:
self.addTarget(ViewController(), action:#selector(ViewController.Test(_:)), for: UIControlEvents.touchDragInside)
En su Controlador de Vista, aquí hay un ejemplo de Acción
@IBAction func Test(_ sender: Any?) {
print("Goodtime was here")
}
En el destino, debe agregar () pero no en el selector de la acción. No tiene que llamar a @IBAction, puede ser solo func. Algunas personas usan @objc o public, cualquiera de esos prefijos en la acción debería funcionar.
Revisión, si la acción está en una clase diferente o ViewController, debe colocar la referencia de clase tanto en el destino como en el selector de la acción. De lo contrario, intentará llamar siempre la acción dentro del mismo archivo independientemente de si es correcto en el Selector. Del mismo modo, si la acción está en el mismo uso de archivo, auto para el objetivo y dentro del selector de la acción.
Aclamaciones
Al agregar objetivos de botón en Swift 3 primero debes estar en class
.
class SomeClass {
// ...
let button = UIButton()
// configure button to taste...
button.addTarget(self,
action: #selector(doSomething),
for: .touchUpInside)
// ...
@objc public func doSomething() {
print("hello, world!")
}
// ...
}