UIGestureRecognizer 不向其他类发送操作
Posted
技术标签:
【中文标题】UIGestureRecognizer 不向其他类发送操作【英文标题】:UIGestureRecognizer not sending action to other class 【发布时间】:2018-06-09 18:05:15 【问题描述】:我正在尝试从 UIView 类上的 UIGestureRecognizer 向其父视图控制器发送操作。
HomeViewController 包含一个包含几个 (5) OperationViews 的视图。
OperationView 扩展了 UIView,看起来像这样:
class OperationView: UIView
override func awakeFromNib()
super.awakeFromNib()
// OperationView is on a view that has HomeViewController as it's controller in StoryBoard
let swipeGestureRecognizer = UISwipeGestureRecognizer(target: HomeViewController.self(), action: #selector(HomeViewController.operatorWasSwiped(_:)))
swipeGestureRecognizer.direction = .left
let tapGestureRecognizer = UITapGestureRecognizer(target: HomeViewController.self(), action: #selector(HomeViewController.operatorWasSwiped(_:)))
self.addGestureRecognizer(swipeGestureRecognizer)
self.addGestureRecognizer(tapGestureRecognizer)
在 HomeViewController 我有这个应该由 UIGestureRecognizers 调用的函数:
@objc func operatorWasSwiped(_ sender : UIGestureRecognizer)
if (sender.isKind(of: UITapGestureRecognizer.self)) print("Tapped")
else print("Swiped")
self.performSegue(withIdentifier: "segue1", sender: nil)
但是,我什么也没得到。甚至没有错误。
我尝试使用 HomeViewController 上的 IBOutlet 将 UIGestureRecognizer 添加到每个 OperationView:
view1.swipeGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view2.swipeGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view3.swipeGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view4.swipeGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view5.swipeGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view1.tapGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view2.tapGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view3.tapGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view4.tapGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view5.tapGestureRecognizer?.addTarget(self, action: #selector(operatorWasSwiped(_ :)))
view1.addGestureRecognizer(view1.swipeGestureRecognizer!)
view2.addGestureRecognizer(view2.swipeGestureRecognizer!)
view3.addGestureRecognizer(view3.swipeGestureRecognizer!)
view4.addGestureRecognizer(view4.swipeGestureRecognizer!)
view.addGestureRecognizer(view5.swipeGestureRecognizer!)
view1.addGestureRecognizer(view1.tapGestureRecognizer!)
view2.addGestureRecognizer(view2.tapGestureRecognizer!)
view3.addGestureRecognizer(view3.tapGestureRecognizer!)
view4.addGestureRecognizer(view4.tapGestureRecognizer!)
view5.addGestureRecognizer(view5.tapGestureRecognizer!)
我添加的地方:
var swipeGestureRecognizer: UISwipeGestureRecognizer?
var tapGestureRecognizer: UITapGestureRecognizer?
为 OperationView 分类变量
这行得通,但它远非优雅(想象一下,如果我必须添加另一个视图......有点违背了我之前的抽象观点)
有什么想法吗?还是我错过了什么?
我正在使用 Swift 4 和 Xcode 9
【问题讨论】:
您需要将对现有的HomeViewController
实例的引用传递给您的手势目标。您的目标当前是一次性实例。
我该怎么做? ViewControllers 很容易知道它们处理什么视图,但是就 MVC 而言,视图通常不知道哪个 ViewController 处理它们。你会建议什么方法?
【参考方案1】:
您正在方法内部创建该手势,并且该手势可能仅在调用该函数时存在于该范围内。所以从技术上讲,在你使用它之前就消失了。因此,在方法之外创建该手势的实例可能会在视图存在时存在。如果这有意义的话。
更新:正如 cmets 所指出的,我们确实需要父 viewController 的当前引用。
这样做怎么样..
class OperationView: UIView
let swipeGestureRecognizer = UISwipeGestureRecognizer()
let tapGestureRecognizer = UITapGestureRecognizer()
override func awakeFromNib()
super.awakeFromNib()
if let parentViewController = parentViewController
swipeGestureRecognizer.addTarget(parentViewController, action: #selector(HomeViewController.operatorWasSwiped(_:)))
swipeGestureRecognizer.direction = .left
tapGestureRecognizer.addTarget(parentViewController, action: #selector(HomeViewController.operatorWasSwiped(_:)))
self.addGestureRecognizer(swipeGestureRecognizer)
self.addGestureRecognizer(tapGestureRecognizer)
extension UIView
var parentViewController: UIViewController?
var parentResponder: UIResponder? = self
while parentResponder != nil
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController
return viewController
return nil
【讨论】:
似乎仍然缺少对当前活动 HomeViewController 的引用。这对你有用吗? '因为它对我不起作用。 这个答案和原代码有同样的问题。它创建了HomeViewController
的无用实例作为每个手势的目标。
@J Arango,仍然让我觉得我已经把自己逼到了墙角,因为这看起来更像是一种黑客行为,而不是一种常规模式。这让我想重新评估我的架构。但是,这确实有效,所以谢谢你:)
是的,这是一个 hack 大声笑,有更好的方法可以做到这一点,但我不知道你是如何处理你的应用程序的架构的。一种方法是将所有视图添加到 IBOutlet 集合中,并通过它们进行交互,将每个视图添加到手势识别器中。这样就有了保存它们的 UIViewController 的引用。以上是关于UIGestureRecognizer 不向其他类发送操作的主要内容,如果未能解决你的问题,请参考以下文章
从另一个类调用选择器的 UIGestureRecognizer