Различное поведение между addTarget и addGestureRecognizer
У меня есть функция, которая создает кнопку с функцией выбора в качестве цели. Адрес кнопки передается handleSelectPhoto
,
lazy var image1Button = createButton(selector: #selector(handleSelectPhoto))
func createButton(selector: Selector) -> UIButton {
let button = UIButton(type: .system)
button.addTarget(self, action: selector, for: .touchUpInside)
return button
}
@objc func handleSelectPhoto(button: UIButton) {
// Do something with button, this works
}
Теперь я пытаюсь изменить класс выше с UIButton на UIImageView, как показано ниже,
lazy var image1Button = createButton(selector: #selector(handleSelectPhoto))
func createButton(selector: Selector) -> UIImageView {
let view = UIImageView()
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: selector))
view.isUserInteractionEnabled = true
return view
}
@objc func handleSelectPhoto(button: UIImageView) {
// HERE, button does not get passed
}
С учетом вышеуказанных изменений в handleSelectPhoto
, экземпляр кнопки неверен. Я не могу прочитать его как тип UIImageView.
Если я добавлю функцию выбора с помощью addGestureRecognizer
, он ведет себя иначе, чем добавление функции выбора с помощью addTarget
с точки зрения того, как функция выбора выполняется с параметрами? Может быть, я не понимаю, как работает эта функция выбора...
2 ответа
Вы должны указать при настройке выбора, что ваша функция примет параметр, добавив :
в конце имени метода.
lazy var image1Button = createButton(selector: #selector(handleSelectPhoto:))
UIKit
автоматически поймет, что параметр методов селектора будет иметь тип UITapGestureRecognizer
, Теперь перепишите нижеприведенный метод, как этот, и вам будет хорошо.
@objc func handleSelectPhoto(gesture: UITapGestureRecognizer) {
if let buttonImageView = gesture.view as? UIImageView {
//Here you can make changes in imageview what ever you want.
}
}
Добавление цели к чему-то вроде UIGestureRecognizer
или же UIButton
передает только один параметр выбранной функции. Этот параметр зависит от типа, к которому вы собираетесь добавить цель.
В вашем случае первый фрагмент кода работает, потому что вы добавляете цель к UIButton
Таким образом, выбранная вами функция получает этот экземпляр UIButton.
Во втором сценарии вы добавляете цель к UITapGestureRecognizer
таким образом, переданный экземпляр будет именно этим распознавателем жестов, который не может быть типа UIImageView
,
Таким образом, разница с точки зрения целевого параметра между UIGestureRecognizer
а также UIButton
нет разницы Они оба передают свои экземпляры выбранной функции.
От UIView
Перспектива подкласса есть разница, что UIGestureRecognizer
не подкласс UIView
, но UIButton
является. Вот почему вы можете просто использовать пройденный UIButton
экземпляр в вашем первом фрагменте. Во втором фрагменте вам нужно использовать свойство view UIGestureRecognizer
,
guard let imageView = gestureRecognizer.view as? UIImageView else { return }
Помимо вашего реального вопроса, кажется, важно уточнить, как писать #selector
правильно. Вы уже делаете это правильно. Никаких изменений не требуется. Некоторые могут сказать, что вам нужно добавить (_:)
или же :
к вашему селектору вот так: #selector(handleSelectPhoto(_:))
но это не правда В общем случае эти специальные символы нужно добавлять только при выборе метода, у которого есть метод перегрузки с другим количеством параметров, но с тем же базовым именем.