Reputation: 361
I've been trying to change the texture of an SKSpriteNode in the scene, but XCode keeps giving me the error "Value of type 'SKNode' has no member 'texture'". However, I put an if is statement, so it should read it as an SKSpriteNode. I'm wondering if there are any other solutions in order to be able to change the texture of an SKSpriteNode in the scene. Thank you!
for child in children {
if child.name == "Enemy" || child.name == "FinalEnemy" {
if child is SKSpriteNode {
child.texture = SKTexture.init(image: #imageLiteral(resourceName: "Ninja58"))
}
}
}
Upvotes: 0
Views: 642
Reputation: 77621
You are asking the runtime environment “is this SKNode actually a SKSpriteNode” but the compiler is still treating child as an SKNode.
You need to get a reference to a SKSpriteNode to make the compiler happy.
You can do that by changing
if child is SKSpriteNode
To
if let child = child as? SKSpriteNode
This second one uses optional binding to create a new variable named child which is valid inside the if block and is a SKSpriteNode.
If child is not a SKSpriteNode then this will pass over this if statement and the code won’t be run so you will have the behaviour you want.
The rest of your code should work by making this change.
Edit after Knight0fDragon's comment
You could actually embed the condition into the for loop here to make it a bit more compact...
for child in children where child.name == "Enemy" || child.name == "FinalEnemy" {
guard let child = child as? SKSpriteNode else { continue }
child.texture = ...
}
Hmm... this isn't as nice as I wanted it and I would like the optional binding in the for loop condition...
Maybe that's possible but this will do for now :)
Edit By Knight0fDragon due to comments being limited:
Please give this a try, should only work in XCode 9+, and the cast may be unnecessary, I do not have access to XCode to test this.
for child in ArraySlice<SKSpriteNode>(children) as [SKSpriteNode]
where ["Enemy","FinalEnemy"].contains(child.name ?? "") {
child.texture = ...
}
Upvotes: 3