2016-03-22 2 views
36

Я переключаю синтаксис моего проекта на Swift 2.2 (который xCode помогает мне делать автоматически); однако, я не понимаю новый синтаксис #selector().Понимание Swift 2.2 Синтаксис селектора - #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, очень ценится.

+2

Думаю, я объясню это красиво здесь: http://stackoverflow.com/questions/35658334/how-do-i-resolve-ambiguous-use-of-compile-error-with-swift-selector-syntax/35658335# 35658335 – matt

+0

Ответ @ matt отвечает более подробно на синтаксис, включая полезное обсуждение работы с перегруженными методами. – Stuart

ответ

31

Биты в скобках представляет собой механизм для идентификации списка аргументов для выбора, который вы хотите.

Я рекомендую вам посмотреть предложение Generalized Naming от 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:) 

Посмотрите, как метки будут добавлены в круглых скобках?

Это предложение сыграло свою роль в той, которая самым непосредственным образом относится к вашему вопросу:

Referencing the Objective-C selector of a method

В данном конкретном случае селектор вы хотите сослаться на это timerCalled:, которая является функцией одного параметра, не имеет метки. Следовательно (_ :). Подчеркивание означает, что метка не указана, а двоеточие.

8

Это то, как сигнатуры метода 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) { ... } 
19

Swift 2.2 устарел Stringified selectors: В swift 2.0 мы используем для записи селектора как строку i.e "buttonClicked". Недостатком такого подхода является то, что компилятор не может проверить, действительно ли метод существует или нет во время компиляции (даже если вы ошибочно указали его).

EX: 1

func buttonClicked(){ 
} 

Таким образом, описанный выше способ в новом подходе можно назвать #selector(buttonClicked)

EX: 2

func buttonClicked(stringValue : String){ 
} 

Таким образом, описанный выше способ в новый подход можно назвать #selector(buttonClicked(_:))

EX: 3

func buttonClicked(stringValue : String, indexValue : Int){ 
} 

Таким образом, описанный выше способ с параметрами в новом подходе можно назвать #selector(buttonClicked(_:indexValue:))

+0

Эй, я только что читал этот вопрос. Не могли бы вы вкратце объяснить мне, почему компилятор установит/изменит ваш вышеприведенный пример на #selector (YourClass.buttonClicked) вместо простого #selector (buttonClicked) при преобразовании в swift 2.2. Есть ли разница между 2? Спасибо – crashoverride777

+0

@ crashoverride777 Я думаю, что ваш вопрос объяснялся здесь явно. Http://stackoverflow.com/questions/24007650/selector-in-swift?rq=1 –

+0

Я думаю, вам всегда нужно префикс объявления метода с помощью @objc – blackjacx

9

Рассмотрим ниже код для добавления цель кнопки в быстрой 3 с помощью #selector

button.addTarget(self, action: #selector(self.buttonAction(sender:)), 
         for: UIControlEvents.touchUpInside) 

func buttonAction(sender:UIButton!){ 

} 

Этот синтаксис работает для меня при переходе на быструю 3

+0

Вопрос о VERSION 2 ... – FonzTech