Skip to content

Instantly share code, notes, and snippets.

@zmeyc
Last active July 11, 2016 12:37
Show Gist options
  • Save zmeyc/58d4c661ff3bb0d35db8 to your computer and use it in GitHub Desktop.
Save zmeyc/58d4c661ff3bb0d35db8 to your computer and use it in GitHub Desktop.
//
// Original Objective C version: https://gist.github.com/bobmoff/7110052
//
// Fix SpriteKit's SKNode bug on iOS 7 & 8: nodes capture touch events
// even when userInteractionEnabled is false and the nodes are hidden.
//
// Details:
// http://stackoverflow.com/questions/19511334/sprite-with-userinteractionenabled-set-to-yes-does-not-receive-touches-when-cove
//
// How to use:
// Use SKSceneWithUserInteractionBugfix class in place of SKScene.
//
import SpriteKit
extension SKNode {
func nodeDepthPriority() -> String {
var code = ""
var currentNode = self
while let parent = currentNode.parent {
var idx = 0
for obj in parent.children {
if obj == currentNode {
code = NSString(format: "%03d%@", idx, code) as String
break
}
++idx
}
currentNode = parent
}
return code
}
}
extension SKScene {
func nodeWithHighestPriority(touches: NSSet) -> SKNode? {
// Only allow touches to be receieved by nodes with userInteractionEnabled, and only the one with the highest touch priority
guard let touch = touches.anyObject() else { return nil }
let touchLocation = touch.locationInNode(self)
let touchedNodes = nodesAtPoint(touchLocation)
var nodeToTouch: SKNode!
for node in touchedNodes {
if node.userInteractionEnabled && !node.hidden && node.alpha > 0 {
if nodeToTouch == nil {
nodeToTouch = node
} else if node.parent == nodeToTouch.parent && node.zPosition > nodeToTouch.zPosition {
nodeToTouch = node
} else if node.parent == nodeToTouch.parent && node.zPosition == nodeToTouch.zPosition && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .OrderedAscending {
nodeToTouch = node
} else if node.parent != nodeToTouch.parent && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .OrderedAscending {
nodeToTouch = node
}
}
}
return nodeToTouch
}
}
public class SKSceneWithUserInteractionBugfix: SKScene {
public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesBegan(touches, withEvent: event)
}
public override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesEnded(touches, withEvent: event)
}
public override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
guard let touches = touches else { return }
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesCancelled(touches, withEvent: event)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment