如何继续触摸/手势到下一个视图控制器

Posted

技术标签:

【中文标题】如何继续触摸/手势到下一个视图控制器【英文标题】:How to continue touches/gesture to next view controller 【发布时间】:2015-01-23 16:44:10 【问题描述】:

我有兴趣在我的项目中开发类似 Snapchat 的手势,其中一个触摸事件将调用一个新的视图控制器,并且只有当用户的手指仍然向下时,视图控制器才可见。

目前,我设法实现了一个wildcard gesture recognizer,其中包含touchesBegantouchesMovedtouchesEnded 的回调块。

var touchesBeganCallback : ((NSSet, UIEvent)-> Void)?
var touchesMovedCallback : ((NSSet, UIEvent)-> Void)?
var touchesEndedCallback : ((NSSet, UIEvent)-> Void)?

在第二个视图控制器通过 segue 显示之前,我添加了一个 wildcard gesture recognizer

destVC.view.addGestureRecognizer(drawWildGestureRecognizer( (touches:NSSet, event:UIEvent) -> Void in
    println("LDetailViewController: touches began")
    , touchesEndedCallback:  (touches:NSSet, event:UIEvent) -> Void in
       println("LDetailViewController: touches ended")
    ))

当然,我的第一个视图控制器已经添加了wildcard gesture recognizer。但是触摸似乎不会继续到我的第二个视图控制器,即使我再次点击我的第二​​个视图控制器的视图并且手势识别器正在正确识别触摸。

我还应该在这里做什么?

【问题讨论】:

你知道 Snapchat 的 touch down 会调用一个新的视图控制器,而不仅仅是一个新的视图吗? 这是我的猜测,所以我的问题是关于继续触摸视图控制器 【参考方案1】:

好吧,您可以获取触摸 NSSetUIEvent 并通过属性将它们传递给新控制器,但这可能没有必要,因为只要用户移动手指,操作系统就会发送新的触摸事件。

我相信窗口中的任何控制器都应该接收新事件。因此,您可以将“didPress”布尔值传递给新控制器,然后侦听要在新控制器上调用的touchesEnded 委托。这应该会给你想要的互动。

请记住,这是即兴表演,因此您可能需要稍微玩一下。

【讨论】:

它不会触发 touchesEnded 没有触发 touchesBegan 先或手动强制它开始 嗯,如何添加新的视图控制器?您是将其添加到导航堆栈中,还是将其添加为子视图控制器?您是否尝试过使用子视图控制器? 我不得不使用子视图控制器来实现这一点【参考方案2】:

我的解决方案分为三个步骤:

    从情节提要中实例化您的子视图控制器,请注意您将为视图控制器设置 storyboardID 以便实例化。

    postDetailViewController = self.storyboard?.instantiateViewControllerWithIdentifier("showPost") as? LDetailViewController
    if postDetailViewController != nil 
      //add child view
      let postDetailView = postDetailViewController!.view
      self.view.addSubview(postDetailView)
    
      //add child view controller
      self.addChildViewController(postDetailViewController!)
      postDetailViewController!.didMoveToParentViewController(self)
     else 
      fatalError("postDetailViewController fails to be created")
    
    

    实现一个通配符手势识别器,它在触摸开始时执行touchesBeganBlocktable view cell 或您希望在父视图控制器中附加此手势的任何其他对象,例如以下:

    var touchesBeganCallback : ((NSSet, UIEvent)-> Void)?
    func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) 
      if (touchesBeganCallback != nil)
        touchesBeganCallback!(touches,event)
      
    
    

    这个touchesBeganBlock 将调用实例化视图控制器的函数(步骤 1 中的代码)

    最后,当触摸结束时,执行一个touchesEndBlock,它只是调用一个函数来丢弃你的子视图控制器:

    var touchesEndedCallback : ((NSSet, UIEvent)-> Void)?
    func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) 
      if (touchesEndedCallback != nil)
        touchesEndedCallback!(touches,event)
      
    
    

    在我的,该块执行以下代码:

    if (postDetailViewController != nil)
      postDetailViewController?.view.removeFromSuperview()
      postDetailViewController?.removeFromParentViewController()
      postDetailViewController = nil
    
    

【讨论】:

您是否有理由使用手势识别器和这些回调,而不是仅在第一个控制器的 self.view 中实现 touchesBegan 和 touchesEnded?这个解决方案不会继续接触下一个视图控制器吗?您只有第一个视图中的一个手势识别器吗? 我想我不太清楚手势识别器的放置位置,它应该放在父视图控制器中。使用自定义手势识别器类的原因是为了使代码更简洁。你可以简单地在你的父视图控制器中调用touchesBegan。只要您使用子视图控制器,就没有任何区别。 另外,视图控制器中的touchesBegan 会拦截视图控制器中发生的所有触摸。这将导致编写一堆 if 语句来在不同的代码之间切换。无论如何,这只是 imo 的可读性问题。

以上是关于如何继续触摸/手势到下一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何将 BLE 活动继续到下一个视图控制器

在下次触摸之前无法接收系统手势状态通知

从 UIScrollview 向前触摸和手势到视图

向左滑动视图控制器到动态视图

如何制作 SwiftUI 手势,在按下视图时继续运行代码

iOS 在处理触摸事件之前执行操作