UIControl addTarget (метод _: action: for :) в Swift 3.2 - PullRequest
0 голосов
/ 16 мая 2018

У меня есть класс, назовем его ClassA со следующим вызовом addTarget.

awesomeBtn.addTarget(nil, action: #selector(awesomeMethod), for: .touchUpInside)

Компилятор принимает приведенную выше строку, когда метод awesomeMethod находится в ClassA (то есть тот же класс, что и вызов addTarget),

Однако, если awesomeMethod НЕ в ClassA, скажем, в ClassB, то компилятор жалуется, и я вынужден указать имя класса в действии.

awesomeBtn.addTarget(nil, action: #selector(ClassB.awesomeMethod), for: .touchUpInside)

В предыдущих версияхиз Swift (точно не знаю, какие версии), я мог бы просто написать следующее, независимо от того, какой класс содержал метод.

awesomeBtn.addTarget(nil, action:("awesomeMethod"), forControlEvents:.touchUpInside)

Хотелось бы понять, почему это так или я что-то не так делаю, спасибо.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

В общем, Свифт хорошо с тобой :) 1001 *

В более старых версиях вы используете строковый литерал или синтаксис Selector(...) для записи селектора. Недостаток этого состоит в том, что нет никакой проверки времени компиляции того, существует ли селектор. Если у вас была опечатка где-то, вы узнаете об этом только во время выполнения. Вам не нужно имя включающего класса, потому что селекторы - это просто имя метода, не включая включающий класс. Во время выполнения собственная логика кнопки найдет этот селектор в переданном вами объекте target. Никто не говорит о том, в каком классе находится селектор. Селектор либо существует в объекте target, либо его нет.

Теперь Swift улучшен и предоставил синтаксис #selector для записи селекторов. проверяет, действительно ли селектор действителен. Компилятор должен искать объявление метода с тем же именем. Вот почему вы должны добавить имя класса, чтобы компилятор знал, где искать. В противном случае он просто будет искать его в текущем классе. Однако это не означает, что селектор всегда будет существовать во время выполнения, потому что во время выполнения кнопка проверяет, есть ли у target этот селектор, поэтому, если вы передаете селектор другого класса (а не класса target) ), кнопка все еще не может найти селектор.

0 голосов
/ 16 мая 2018

Да, они изменили его с String, где это была просто ошибка во время выполнения, если вы неправильно набрали имя метода на #selector, который вызывает проверку времени компиляции для метода.Они просто пытаются найти ваши ошибки раньше.

Однако, если awesomeMethod НЕ в ClassA, скажем, в ClassB, то компилятор жалуется, и я вынужден указать имя класса вaction.

Нет, вы можете указать @objc protocol, который реализует метод:

@objc protocol AwesomeProtocol {
    func awesomeMethod()
}

Тогда, даже если ваш класс не реализует этот метод,Вы можете указать:

awesomeBtn.addTarget(nil, action: #selector(AwesomeProtocol.awesomeMethod), for: .touchUpInside)

Примечание: никому не нужно принимать этот протокол.Кнопка ищет цепочку респондента и использует первый найденный метод сопоставления.Хотя вы должны принять протокол любым классом, который реализует awesomeMethod, чтобы Swift мог обнаруживать ошибки в сигнатуре метода во время компиляции.

...