UIButton 不受 UITapGestureRecoginzer 的影响。
UIButton is not affected by UITapGestureRecoginzer.
我有一个 UIImageView
(userInteractionEnabled) UIButton
和 UITextField
都是 superview 的子视图,其中添加了一个 UITapGestureRecognizer
。所以我的 superview
和 UIImageView
是 响应 来点击手势但是 UIButton
和 UITextField
忽略 它。这是我的错添加到 superview 的 UITapGestureRecognizer 策略吗?请问有人知道这种情况吗?
这是我的带有视图子视图和手势识别器的代码
@objc func tapBlurButton(_ sender: UITapGestureRecognizer) {
print("Please Help!")
endEditing(true)
}
override init(frame: CGRect) {
super.init(frame: frame)
// backgroundColor = UIColor.green
addSubview(logoImageView)
// addSubview(skipButton)
addSubview(emailTextField)
addSubview(passwordTextField)
addSubview(loginButton)
observeKeyboardNotifications()
// logoImageView.translatesAutoresizingMaskIntoConstraints = false
logoImageView.anchorWithConstantsToTop(centerYAnchor, left: nil , bottom: nil, right: nil, topConstant: -230, leftConstant: 0, bottomConstant: 0, rightConstant: 0)
logoImageView.widthAnchor.constraint(equalToConstant: 160).isActive = true
logoImageView.heightAnchor.constraint(equalToConstant: 160).isActive = true
logoImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
emailTextField.anchorWithConstantsToTop(logoImageView.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 8, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
passwordTextField.anchorWithConstantsToTop(emailTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 8, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
passwordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
loginButton.anchorWithConstantsToTop(passwordTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 16, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
loginButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
isUserInteractionEnabled = true
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(LoginCell.tapBlurButton(_:))))
isUserInteractionEnabled = true
}
我看到其他答案,他们只是告诉如何解决它,但他们没有说明发生这种情况的真正原因,而且没有人参考确切说明此问题的文档。所以我的问题不是问如何避免它或如何解决它,我想知道它为什么会发生,当我怀疑 UIkit 这样做时我是对的所以这不是我的错或者我错了错过了什么?
Apple 有一篇非常简单且有用的文章。要了解您想要什么,您应该查看 Responder Chain 概念。
Understanding Event Handling, Responders, and the Responder Chain
基本上,如果您想了解为什么您的 UIImageView
响应 点击,但 UIButton
和 UITextField
不要这样做,有一个简单的解释。 UIButton
和UITextField
是UIControl
的子类,UIImageView
不是,只是UIResponder
的子类。所以,每个UIControl
都使用Target-Action机制,但是UIResponder
不这样做。
文档说:
Controls communicate directly with their associated target object
using action messages. When the user interacts with a control, the
control calls the action method of its target object—in other words,
it sends an action message to its target object. Action messages are
not events, but they may still take advantage of the responder chain.
When the target object of a control is nil, UIKit starts from the
target object and walks the responder chain until it finds an object
that implements the appropriate action method.
因此,这意味着 默认情况下 当您单击 UIControl
对象时,它不会将该事件传播到超级视图来处理它。控件覆盖默认 UIResponder
行为。但是当你点击一个UIResponder
的时候,它会将事件发送给superview去处理,touch落空了。因此,UIKit
会执行此操作,而通常的 UITapGestureRecognizer
s 默认情况下不会经过 UIControl
s,因为控件具有其预设事件集并使用另一种机制来处理它们。但是当您禁用 UIControl
与用户点击交互的能力时,您的 superview 点击手势识别器将会响应。
在你的例子中,如果你设置了它,即使你按下按钮,你的 func tapBlurButton(_ sender: UITapGestureRecognizer)
也会被调用,因为那个按钮不会尝试处理事件,触摸只会落到超级视图。
loginButton.isUserInteractionEnabled = false
我有一个 UIImageView
(userInteractionEnabled) UIButton
和 UITextField
都是 superview 的子视图,其中添加了一个 UITapGestureRecognizer
。所以我的 superview
和 UIImageView
是 响应 来点击手势但是 UIButton
和 UITextField
忽略 它。这是我的错添加到 superview 的 UITapGestureRecognizer 策略吗?请问有人知道这种情况吗?
这是我的带有视图子视图和手势识别器的代码
@objc func tapBlurButton(_ sender: UITapGestureRecognizer) {
print("Please Help!")
endEditing(true)
}
override init(frame: CGRect) {
super.init(frame: frame)
// backgroundColor = UIColor.green
addSubview(logoImageView)
// addSubview(skipButton)
addSubview(emailTextField)
addSubview(passwordTextField)
addSubview(loginButton)
observeKeyboardNotifications()
// logoImageView.translatesAutoresizingMaskIntoConstraints = false
logoImageView.anchorWithConstantsToTop(centerYAnchor, left: nil , bottom: nil, right: nil, topConstant: -230, leftConstant: 0, bottomConstant: 0, rightConstant: 0)
logoImageView.widthAnchor.constraint(equalToConstant: 160).isActive = true
logoImageView.heightAnchor.constraint(equalToConstant: 160).isActive = true
logoImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
emailTextField.anchorWithConstantsToTop(logoImageView.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 8, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
passwordTextField.anchorWithConstantsToTop(emailTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 8, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
passwordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
loginButton.anchorWithConstantsToTop(passwordTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 16, leftConstant: 32, bottomConstant: 0, rightConstant: 32)
loginButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
isUserInteractionEnabled = true
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(LoginCell.tapBlurButton(_:))))
isUserInteractionEnabled = true
}
我看到其他答案,他们只是告诉如何解决它,但他们没有说明发生这种情况的真正原因,而且没有人参考确切说明此问题的文档。所以我的问题不是问如何避免它或如何解决它,我想知道它为什么会发生,当我怀疑 UIkit 这样做时我是对的所以这不是我的错或者我错了错过了什么?
Apple 有一篇非常简单且有用的文章。要了解您想要什么,您应该查看 Responder Chain 概念。
Understanding Event Handling, Responders, and the Responder Chain
基本上,如果您想了解为什么您的 UIImageView
响应 点击,但 UIButton
和 UITextField
不要这样做,有一个简单的解释。 UIButton
和UITextField
是UIControl
的子类,UIImageView
不是,只是UIResponder
的子类。所以,每个UIControl
都使用Target-Action机制,但是UIResponder
不这样做。
文档说:
Controls communicate directly with their associated target object using action messages. When the user interacts with a control, the control calls the action method of its target object—in other words, it sends an action message to its target object. Action messages are not events, but they may still take advantage of the responder chain. When the target object of a control is nil, UIKit starts from the target object and walks the responder chain until it finds an object that implements the appropriate action method.
因此,这意味着 默认情况下 当您单击 UIControl
对象时,它不会将该事件传播到超级视图来处理它。控件覆盖默认 UIResponder
行为。但是当你点击一个UIResponder
的时候,它会将事件发送给superview去处理,touch落空了。因此,UIKit
会执行此操作,而通常的 UITapGestureRecognizer
s 默认情况下不会经过 UIControl
s,因为控件具有其预设事件集并使用另一种机制来处理它们。但是当您禁用 UIControl
与用户点击交互的能力时,您的 superview 点击手势识别器将会响应。
在你的例子中,如果你设置了它,即使你按下按钮,你的 func tapBlurButton(_ sender: UITapGestureRecognizer)
也会被调用,因为那个按钮不会尝试处理事件,触摸只会落到超级视图。
loginButton.isUserInteractionEnabled = false