Что такое селектор в iOS и как работает target-action?
Что проверяют
Знаете ли вы, что под UIKit лежит рантайм Objective-C, и понимаете ли, чем имя метода отличается от ссылки на него. Вопрос простой на словах, но по ответу видно, приходилось ли вам ловить падение с unrecognized selector и объяснять, почему оно вообще возможно в Swift.
Как отвечать
Селектор это имя метода, а не указатель на реализацию: тип SEL хранит уникализированную строку, по которой рантайм ищет реализацию в таблице методов класса уже во время выполнения. Отсюда главное свойство: селектор не привязан к классу, и проверить его применимость можно только вызовом responds(to:).
Target-action это пара, которую контрол хранит у себя: объект-получатель и селектор.
button.addTarget(self, action: #selector(tapped(_:)), for: .touchUpInside)
@objc private func tapped(_ sender: UIButton) { }Три вещи стоит назвать отдельно. Метод должен быть виден рантайму Objective-C, то есть помечен @objc в классе, наследующем NSObject. Допустимы только три формы сигнатуры: без параметров, с отправителем, с отправителем и событием. Ссылка на получателя слабая, поэтому цикла удержания здесь не возникает, а если получатель освобождён, действие просто не отправляется.
Полезно добавить, что при пустом получателе действие уходит по цепочке респондеров и его подхватывает первый, кто отвечает на этот селектор. В современных версиях UIKit ту же задачу закрывает объект действия с замыканием, и в новом коде обычно берут его.
Где спотыкаются
Называют селектор указателем на метод. Из-за этого не могут объяснить, почему опечатка в строковой форме спокойно компилируется и падает только при нажатии: конструкция #selector проверяется на сборке, строка не проверяется ничем.
Забывают про @objc. Атрибут давно не выводится сам, метод обычного класса Swift рантайму не виден, а для структуры и для метода в расширении протокола target-action не заработает вовсе.
Ищут утечку памяти там, где её нет. Контрол держит получателя слабо, поэтому подписка на себя цикла не создаёт. Зато его легко создать замыканием в объекте действия, если внутри сильно захвачен контроллер.