Swift хочет, чтобы аргумент #selector подвергался воздействию Objective-C
У меня есть проект Swift, где я хочу привязать метод к событию крана UIButton. У меня есть следующий код:
class MyClass {
let myButton = UIButton(frame: CGRectMake(50, 50, 100, 50))
init() {
myButton.addTarget(self, #selector(self.didTap(_:)), forControlEvents: .TouchUpInside)
}
func didTap(sender: UIButton) {
print("Tapped")
}
}
XCode выделяет мою строку addTarget
и говорит:
Argument of '#selector' refers to a method that is not exposed to Objective-C
Если я добавлю префикс @objc
к моему func didTap
, как он предлагает, все будет хорошо.
У меня что-то включено в моих настройках сборки, что вызывает это странное поведение?
PS. Я получаю это поведение в 7.3.1. Но если я попробую это в 7.2.1, он не примет синтаксис #selector(method(_:))
, а Selector("method:")
отлично работает.
Ответы
Ответ 1
Селекторы - это функция Objective-C и могут использоваться только с методами, которые подвергаются динамической среде выполнения Obj-C. Вы не можете выбрать селектор для чистого метода Swift.
Если ваш класс наследует от NSObject
, то его общедоступные методы автоматически отображаются в Obj-C. Так как ваш класс не наследует от NSObject
, вам нужно использовать атрибут @objc
, чтобы указать, что вы хотите, чтобы этот метод подвергался Obj-C, чтобы его можно было вызвать с помощью селектора Obj-C.
#selector()
- новый синтаксис в Swift 2.2. Это позволяет компилятору проверить, что селектор, который вы пытаетесь использовать, фактически существует. Старый синтаксис устарел и будет удален в Swift 3.0.
Ответ 2
Если я добавлю префикс @objc к своему func didTap
, как он предлагает, все будет хорошо.
У меня что-то включено в моих настройках сборки, что вызывает это странное поведение?
Нет. То, что вы видите, нормально. Селекторы - это функция Objective-C, и поэтому используется селектор для отправки сообщения в экземпляр класса. Единственный способ Objective-C может отправить это сообщение, если он может видеть ваш класс или сам метод. MyClass сам по себе не получен из NSObject, поэтому Objective-C не может его видеть. Поэтому, если вы не хотите выводить его из NSObject, вам по крайней мере нужно выставить метод Objective-C, пометив его @objc
.
и Selector ( "method:" ) отлично работает
В более ранних версиях Swift компилятор не помог вам в этой ситуации, поэтому ваш код будет компилироваться. Но вы столкнулись бы с сообщением, и Objective-C не смог найти метод. Весь смысл синтаксиса #selector
- помочь вам избежать этого сбоя. И это именно то, что он сделал!
Ответ 3
У вас должен быть подкласс от NSObject