I have somehow lost the ability to receive touch notifications

Two days ago I was able to receive touchesBegan (moved, canceled) and now I've lost them. So I shortened the code below, created an SKSpriteNode called redSprite within GameScene...and still I don't receive touches.

While I know my redSprite doesn't fulfill all the if's in the touch functions, I'm placing a breakpoint at the start of the touch functions, and it still won't stop at the breakpoint.

However...if I set GameScene's isUserInteractionEnabled to true, then I do get the touches and the debugger breaks.

Code Block
import UIKit
import SpriteKit
var redSprite : SKSpriteNode?
class GameScene: SKScene, SKPhysicsContactDelegate {
override func sceneDidLoad(){
super.sceneDidLoad()
#if DEBUG
print ("GC sceneDidLoad")
#endif
}
override func didMove(to view: SKView){
super.didMove(to: view)
#if DEBUG
print ("GC didMove START")
#endif
self.isHidden = true
self.backgroundColor = mySafeColor
myGlobalVars.backGround = SKSpriteNode(imageNamed: "background")
myGlobalVars.backGround!.zPosition = theZ.backGround
myGlobalVars.safeSceneRect = view.frame
myGlobalVars.gameScene = self
self.isHidden = false
self.isUserInteractionEnabled = false
self.addChild(myGlobalVars.backGround!)
physicsWorld.contactDelegate = self
redSprite = SKSpriteNode(color: .red, size: CGSize(width: 100, height: 100))
redSprite?.anchorPoint = CGPoint(x: 0.5, y:0.5)
redSprite?.isHidden = false
redSprite?.isUserInteractionEnabled = true
redSprite?.color = .orange
redSprite!.name = "test"
redSprite?.zPosition = 10
redSprite?.position = CGPoint(x: (myGlobalVars.safeSceneRect.width/2)-(50), y: myGlobalVars.safeSceneRect.height/2 - 50)
redSprite?.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 100, height: 100), center: CGPoint(x: 0.5, y: 0.5))
redSprite?.physicsBody!.affectedByGravity = false
redSprite?.physicsBody!.restitution = 0.2
redSprite?.physicsBody?.categoryBitMask = bodyMasks.blankMask.rawValue
redSprite?.physicsBody?.contactTestBitMask = bodyMasks.blankMask.rawValue
redSprite?.physicsBody?.collisionBitMask = bodyMasks.blankMask.rawValue
self.addChild(redSprite!)
gameTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runTimedCode), userInfo: nil, repeats: true)
gameTimer?.tolerance = 0.2
RunLoop.current.add(gameTimer!, forMode: .common)
#if DEBUG
print ("GC didMove END")
#endif
}
override func touchesBegan(_ touches: Set<UITouch>,
with event: UIEvent?){
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let touchedNodes = self.nodes(at: location)
for node in touchedNodes{
if let theNode = node as? MyGem {
if theNode.nodeType == NodeType.gem, theNode.isMoving == false {
theNode.isMoving = true
theNode.zPosition += 1
myGlobalVars.currentGem = theNode
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
guard touches.first != nil else { return }
if let touch = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
let touchLocation = touch.location(in: self)
node.position = touchLocation
node.isMoving = true
node.inSlot = false
//addTrailToTwinkle(theNode: node)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard touches.first != nil else { return }
if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
returnHome(moveThis : node, origNP: node.origPoint)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
guard touches.first != nil else { return }
if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
returnHome(moveThis : node, origNP: node.origPoint)
}
}
@objc func runTimedCode() {
timeLeft -= 1
}
}

Answered by Claude31 in 645859022
When you set to false, you cascade to subviews as well, whatever you set them.

See discussion here:
https://stackoverflow.com/questions/5887305/uiview-user-interaction-enabled-false-on-parent-but-true-on-child


userInteractionEnabled set to NO on a parent view will cascade down to all subviews. If you need some subviews to have interaction enabled, but not others, you can separate your subviews into two parent views: one with userInteractionEnabled = YES and the other NO. 


All it does is make sure I get touches for the screen itself, not its children

True. And the method touchesBegan(_:with:) defined in GameScene detect touches for the scene, not its children.

All it does is make sure I get touches for the screen itself, not its children
True. And the method touchesBegan(_:with:) defined in GameScene detect touches for the scene, not its children.

But that's the thing, I need to get the touches for the children, which I was doing before I decided to clean everything up.

I've zipped the real sloppy version and it's here if you'd like to try:

warptv.com/DropSlot.zip

Only GameScene has touchesBegan, but it gets all the touches for the balls, which is what I want. Yet, I hav no idea how I lost it.

p.s. better to run it on a n iPhone X simulator...hadn't worked on resizing here.

p.p.s. Please excuse how sloppy all the code is...it was my first attempt

I need to get the touches for the children, which I was doing before I decided to clean everything up.

As far as I see inside your DropSlot.zip, you are clearly doing self.isUserInteractionEnabled = true.

Setting that to false is a wrong attempt to fix your issue. Better make it back to true and find what's wrong with your current code.
(Though, I'm not sure what is your actually current code.)
Accepted Answer
When you set to false, you cascade to subviews as well, whatever you set them.

See discussion here:
https://stackoverflow.com/questions/5887305/uiview-user-interaction-enabled-false-on-parent-but-true-on-child


userInteractionEnabled set to NO on a parent view will cascade down to all subviews. If you need some subviews to have interaction enabled, but not others, you can separate your subviews into two parent views: one with userInteractionEnabled = YES and the other NO. 



userInteractionEnabled set to NO on a parent view will cascade down to all subviews. If you need some subviews to have interaction
enabled, but not others, you can separate your subviews into two parent views: one with userInteractionEnabled = YES and the
other NO. 

So....it appears that if I do the following for every child :

Code Block
isUserInteractionEnabled = false

and ONLY set it to true for GameScene (the parent)

That I get the cascade of touches, and can for loop through the nodes. Was that what I was doing wrong? Was it that simple of an error? If so I am both relieved and furious with myself at the same time.


Please tell if that works now with this new isUserInteractionEnabled settings.
And close the thread if OK.

But for sure, the parent view must be userEnabled.
I have somehow lost the ability to receive touch notifications
 
 
Q