addTarget和addGestureRecognizer之间的不同行为

问题描述 投票:0回答:2

我有一个函数创建一个按钮,选择器功能作为目标。按钮的地址传递给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添加选择器函数的方式不同,就如何使用参数执行选择器函数而言?也许我不明白这个选择器功能如何工作......

swift uigesturerecognizer selector addtarget
2个回答
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.
        }
}

2
投票

将目标添加到UIGestureRecognizerUIButton之类的只会将一个参数传递给所选函数。此参数取决于您要添加目标的类型。

在您的情况下,第一个代码片段可以正常工作,因为您要将目标添加到UIButton,因此您选择的函数将传递给此UIButton实例。

在第二个场景中,您将目标添加到UITapGestureRecognizer,因此传递的实例将是这个手势识别器,它不能是UIImageView类型。

因此,与UIGestureRecognizerUIButton之间的目标参数视角的差异没有区别。它们都将实例传递给选定的函数。

UIView子类的角度来看,UIGestureRecognizer不是UIView的子类,但是UIButton是不同的。这就是为什么你可以在你的第一个片段中使用传递的UIButton实例。在第二个片段中,您需要使用UIGestureRecognizer的view属性。

guard let imageView = gestureRecognizer.view as? UIImageView else { return }

除了你的实际问题,澄清如何正确编写#selectors似乎很重要。你已经做到了。无需更改。有些人可能会说你需要将(_:):添加到你的选择器中:#selector(handleSelectPhoto(_:))但这不是真的。通常,在选择具有不同参数量但具有相同基本名称的重载方法的方法时,只需添加这些特殊字符。

© www.soinside.com 2019 - 2024. All rights reserved.