Понимание Swift 2.2 Синтаксис селектора - #selector()
Я переключаю синтаксис моего проекта на Swift 2.2 (который xCode помогает мне делать автоматически); однако я не понимаю новый синтаксис #selector()
.
В качестве примера:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self,
selector: #selector(MyVC.timerCalled(_:)), //new selector syntax!
userInfo: nil, repeats: true)
У этого есть селектор #selector(MyVC.timerCalled(_:))
Что означает _:
? Можете ли вы добавить в этот селектор другие переменные? Скажем, #MyVC.timerCalled(_:whateverVar)
.
Общая информация о том, что отличается в этом синтаксисе, в отличие от реализаций на основе строк из более ранних версий Swift, очень ценится.
Ответы
Ответ 1
Бит в скобках - это механизм для определения списка аргументов для селектора, который вы хотите.
Я рекомендую вам ознакомиться с предложением Обобщенные именa > от Swift Evolution. Он охватывает случаи, когда у вас есть ряд функций, которые отличаются только их метками параметров и должны обращаться к ним. Пример из этого документа:
extension UIView {
func insertSubview(view: UIView, at index: Int)
func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}
Если вы хотите получить значение функции для одного из них, результат будет неоднозначным:
let fn = someView.insertSubview // ambiguous: could be any of the three methods
Реализованное решение заключается в добавлении ярлыков аргументов без какой-либо информации типа в код, который генерирует значение функции, которое необходимо устранить, если вы хотите:
let fn = someView.insertSubview(_:at:)
let fn1 = someView.insertSubview(_:aboveSubview:)
Посмотрите, как метки добавляются в parens?
Это предложение сыграло свою роль в том, что наиболее непосредственно относится к вашему вопросу:
Ссылка на селектор Objective-C метода
В этом конкретном случае селектором, к которому вы хотите обратиться, является timerCalled:
, который является функцией одного параметра, который не имеет метки. Следовательно (_:). Подчеркивание означает, что метка не указана и двоеточие.
Ответ 2
Swift 2.2 устарел Stringified selectors: в Swift 2.0 мы используем для записи селектора как строку i.e "buttonClicked"
. Недостатком такого подхода является то, что компилятор не может проверить, действительно ли метод существует или нет во время компиляции (даже если у вас есть опечатка).
ЕХ: 1
func buttonClicked(){
}
Таким образом, вышеупомянутый метод в новом подходе можно назвать #selector(buttonClicked)
EX: 2
func buttonClicked(stringValue : String){
}
Таким образом, вышеупомянутый метод в новом подходе можно назвать #selector(buttonClicked(_:))
ЕХ: 3
func buttonClicked(stringValue : String, indexValue : Int){
}
Таким образом, описанный выше метод с параметрами нового подхода можно назвать #selector(buttonClicked(_:indexValue:))
Ответ 3
Рассмотрим ниже код для добавления цели в кнопку в swift 3 с помощью #selector
button.addTarget(self, action: #selector(self.buttonAction(sender:)),
for: UIControlEvents.touchUpInside)
func buttonAction(sender:UIButton!){
}
Этот синтаксис работал у меня при переходе на быстрый 3
Ответ 4
Это то, как сигнатуры метода Swift представлены в документации, и теперь она начинает использоваться в новых языковых возможностях, таких как синтаксис #selector()
, чтобы выражать методы в своих списках аргументов.
Каждый двоеточие (:
) представляет параметр метода. Для именованных параметров двоеточие предшествует имени внешнего параметра; для неименованных параметров используется символ подчеркивания (_
).
Так, например, MyVC.timerCalled(_:))
указывает метод типа MyVC
с одним неназванным параметром, который может быть объявлен следующим образом:
func timerCalled(timer: NSTimer) { ... }
(Обратите внимание, что timer
- это имя внутреннего параметра, поскольку по умолчанию первый параметр метода не указан)
Тип (MyVC
в вашем примере) также может быть опущен, если он находится в пределах той же области объявления #selector()
.
Более сложный пример может выглядеть так:
let sel = #selector(aMethodWithSeveralParameters(_:secondParam:thirdParam:))
...
func aMethodWithSeveralParameters(firstParam: Int, secondParam: Int, thirdParam: Int) { ... }