Swift Spritekit 3D Touch and Touches Moved

Swift SpriteKit 3D Touch and touches moved

After trying various other things that didnt work, including UISwipeGestureRecognizer subclasses, I finally figured it out.

The answer was actually staring me right in the face in that same stackOverflow post I linked in my question

iOS 9 Spritekit Double Tap Not Working on iPhone 6S

The solution is to create a property

var startingTouchLocation: CGPoint?

than in touches Began you set that property

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

....
}
}

and than add a check in touchesMoved to return from the method until the touch has actually moved.

 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
....
}
}

Distinguish Swipe from Touch in Spritekit - Swift 3

You can use a gestures state to fine tune user interaction. Gestures are coordinated, so shouldn't interfere with each other.

func handlePanFrom(recognizer: UIPanGestureRecognizer) {
if recognizer.state != .changed {
return
}

// Handle pan here
}

func handleTapFrom(recognizer: UITapGestureRecognizer) {
if recognizer.state != .ended {
return
}

// Handle tap here
}

3D Touch force gesture activates cell tap on touch end

You could create a boolean named isForceTouch which is set to false in touchesBegan, and then once force touch is detected, set it to true. Then in didSelectRowAtIndexPath just return false if isForceTouch is true. It may need tweaking but that should work.

3D Touch and SpriteKit

Yes, you can integrate 3D Touch and SpriteKit.

Using the default SpriteKit game project template (Swift), set your GameScene to be a UIViewControllerPreviewingDelegate and implement the protocol's methods, like this:

public class GameScene: SKScene, UIViewControllerPreviewingDelegate {
public func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
return UIViewController()
}

//Pop
public func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
return
}
}

In GameViewController.swift's viewDidLoad, add the following:

if let scene = GameScene(fileNamed:"GameScene") {
if self.traitCollection.forceTouchCapability == .Available {
registerForPreviewingWithDelegate(scene, sourceView: scene.view!)
}
}

In the delegate method, I am returning an empty view controller. You can create a class-level variable and instantiate this VC with appropriate peek-type views. Again, a very simple example. If you want to add 3D Touch from an AppIcon interaction, you will need to modify Info.plist and add capabilities from the AppDelegate. There is a good video on this topic. Good luck!



Related Topics



Leave a reply



Submit