Swift SpriteKit 3D Touch 和触摸移动

Swift SpriteKit 3D Touch and touches moved

我最近将我的游戏版本发送给 TestFlight 进行内部测试。 我的朋友注意到他的 iPhone 6S Plus 上的射击控件无法正常工作。

控件如下

1) 左半屏 = 跳转

2) 屏幕右半边 = 射击

3) 滑动并按住屏幕的右半部分 = 开始慢动作

现在,在我的 touches begin 方法中,我的拍摄有轻微的延迟,因此如果调用 touches moved,它会取消拍摄并开始慢动作。 这似乎是启用 3D Touch 的手机出现问题的原因。

进一步深入研究,我发现了这个 post

它基本上指出在支持 3D Touch 的设备上自动调用 touches moved 方法。

  On 3D Touch capable devices, touch pressure changes cause     
   touchesMoved:withEvent: to be called for all apps running on iOS   
   9.0. When running iOS 9.1, the method is called only for apps  
   linked with the iOS 9.0 (or later) SDK.

    Apps should be prepared to receive touch move events with no   
    change in the x/y coordinates. "

这似乎解释了为什么我的朋友有问题,如果总是调用 touches moved 它将取消拍摄并开始慢动作,即使他没有在屏幕上滑动。

所以我的问题是

1) 能否在 SpriteKit 游戏中禁用 3D Touch?

2) 这是一个错误吗?

3) 还有其他方法可以使用在 3D Touch 设备上正确移动的触摸吗?

4) 或者,我可以使用手势识别器来模拟我当前在 touches moved 中执行的滑动和保持功能。

感谢您的帮助

在尝试了各种其他无效的方法(包括 UISwipeGestureRecognizer 子类)之后,我终于弄明白了。

答案实际上就在同一个 Whosebug post 我在我的问题中链接

解决方案是创建一个 属性

var startingTouchLocation: CGPoint?

比在 touches Begin 你设置的那个 属性

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)

        /// Set starting touch. this is for 3d touch enabled devices, see touchesMoved method below
        startingTouchLocation = location


        ....
     }
 }

然后在 touchesMoved 方法中添加一个检查到 return,直到触摸实际移动。

 override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)

        /// WAY 1 - Check if touch moved because on 3d touch devices this method gets called on a force touch.
        guard location != startingTouchLocation else { return }

        // Your code
        ...

        /// WAY 2 - Add a min distance for the finger to travel in any direction before calling touches moved code
        let minValue: CGFloat = 30
        guard let startingLocation = startingLocation else { return }

        guard currentLocation.y < startingLocation.y - minValue ||
        currentLocation.y > startingLocation.y + minValue ||
        currentLocation.x < startingLocation.x - minValue ||
        currentLocation.x > startingLocation.x + minValue else { return  false }

       // Your code 
       ....
     }
  }