我有一个函数创建一个按钮,选择器功能作为目标。按钮的地址传递给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
添加选择器函数的方式不同,就如何使用参数执行选择器函数而言?也许我不明白这个选择器功能如何工作......
在设置选择时,您应该通过在方法名称末尾添加:
来接受参数。
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
实例。在第二个片段中,您需要使用UIGestureRecognizer
的view属性。
guard let imageView = gestureRecognizer.view as? UIImageView else { return }
除了你的实际问题,澄清如何正确编写#selector
s似乎很重要。你已经做到了。无需更改。有些人可能会说你需要将(_:)
或:
添加到你的选择器中:#selector(handleSelectPhoto(_:))
但这不是真的。通常,在选择具有不同参数量但具有相同基本名称的重载方法的方法时,只需添加这些特殊字符。