我有一个函数,该函数创建一个以选择器函数为目标的按钮。按钮的地址将传递到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
添加选择器功能不同吗?也许我不了解此选择器功能的工作原理...
答案 0 :(得分:2)
将目标添加到UIGestureRecognizer
或UIButton
之类的东西只会将一个参数传递给所选函数。此参数取决于您要添加目标的类型。
在您的情况下,第一个代码段有效,因为您要向UIButton
添加 target ,因此您选择的函数将通过此UIButton实例传递。
在第二种情况下,将 target 添加到UITapGestureRecognizer
,因此传递的实例将正是此手势识别器,不能是{ {1}}。
因此,从{em> target参数角度来看,UIImageView
和UIGestureRecognizer
之间没有区别。它们都将实例传递给选定的函数。
从UIButton
子类的角度来看,区别在于UIView
不是UIGestureRecognizer
的子类,而UIView
是。这就是为什么您只能在第一个代码段中使用传递的UIButton
实例。在第二个代码段中,您需要使用UIButton
的 view属性。
UIGestureRecognizer
除了您的实际问题之外,弄清如何正确编写guard let imageView = gestureRecognizer.view as? UIImageView else { return }
似乎很重要。 您已经将其纠正了。无需更改。有人可能说您需要像这样将#selector
或(_:)
添加到选择器::
,但这不是事实。通常,仅在选择具有重载方法且参数数量不同但基本名称相同的方法时,才需要添加这些特殊字符。
答案 1 :(得分:1)
在设置选择时,应在方法名称的末尾添加:
来告诉您函数将接受参数。
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.
}
}