Reputation: 123
I have a strange problem with Swiperecognizer.
I have spawning objects on screen.
let SpawnObject = SKAction.run({
() in
showobject()
})
let delay1 = SKAction.wait(forDuration: 0.9)
let SpawnDelay1 = SKAction.sequence([SpawnObject,delay1])
let SpawnDelayForever1 = SKAction.repeatForever(SpawnDelay1)
self.run(SpawnDelayForever1)
let distance = CGFloat(self.frame.height + 200)
let moveObject = SKAction.moveBy(x: -distance, y: 0, duration: TimeInterval(0.004 * distance))
let removeObject = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([moveObject,removeObject])
I have object with some physics (Object2, B.png is similar).
func showObject(){
let texture = SKTexture(imageNamed: "A.png")
object = SKSpriteNode(texture: texture)
object.name = "A"
object.position = CGPoint(x: 0, y: self.frame.width)
object.setScale(0.7)
object.zPosition = 2
object.run(moveAndRemove)
object.physicsBody = SKPhysicsBody(texture: texture, size: texture.size())
object.physicsBody?.categoryBitMask = PhysicsCategory.Object
object.physicsBody?.collisionBitMask = PhysicsCategory.Object2
object.physicsBody?.contactTestBitMask = PhysicsCategory.Object2
object.physicsBody?.affectedByGravity = false
object.physicsBody?.isDynamic = true
addChild(object)
}
I have set swipe recognizer in touchesBegan
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
location = touch.location(in: self)
node = self.atPoint(location)
if node.name == "A" {
//node.run(SKAction.moveBy(x: 1000, y: 0, duration: 1)). //Here I try set action only to touch
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(rightSlide(_:)))
rightSwipe.direction = .right
view!.addGestureRecognizer(rightSwipe)
}
else if node.name == "B" {
//node.run(SKAction.moveBy(x: -1000, y: 0, duration: 1)). //Here I try set action only to touch
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(leftSlide(_:)))
leftSwipe.direction = .left
view!.addGestureRecognizer(leftSwipe)
}else {print ("Blank space")}
}
}
func leftSlide(_ sender: UISwipeGestureRecognizer){
if node.name == "B" {
node.run(SKAction.moveBy(x: -1000, y: 0, duration: 1))
}else {print ("Bad swipe")}
}
func rightSlide(_ sender: UISwipeGestureRecognizer){
if node.name == "A" {
node.run(SKAction.moveBy(x: 1000, y: 0, duration: 1))
}else {print ("Bad swipe")}
}
And now the problem. Objects are showing on screen, when I swipe on them, they disappear to side. Everything works fine until I swipe something about 50 objects away, after that every next swipe freeze app for microsecond, objects weird jumps a few pixels down (more swipes, more pixels) and back to their original position and after this weird behavior object swipe away. More swipes = bigger freeze and bigger jumps.
I try turn off physics and nothing. But when I change action directly to touch (no need swipe, just touch), app works fine forever. So there must be wrong swipe recognizer. Or not? I check CPU and MEMORY and CPU has 35% and memory are about 50MB. Nodes on screen max 20. FPS are 60 but when app freeze, it goes down to 58 (Like flickering).
Any suggestion? How to diagnose where is problem? Thanks!
Upvotes: 1
Views: 77
Reputation: 13675
Instead of adding a recognizer every time in touchesBegan method, you should do the following:
1) Create an array to store all recognizers, so you can remove them later easily
2) Add recognizers only once. Note that recognizers are added to the view, not to the scene
3) Remove them when the scene is about to remove from a view
import SpriteKit
class GameScene: SKScene,SKPhysicsContactDelegate {
var recognizers:[UIGestureRecognizer] = []
override func didMove(to view: SKView) {
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.leftSlide(recognizer:)))
leftSwipe.direction = .left
leftSwipe.numberOfTouchesRequired = 1
self.view?.addGestureRecognizer(leftSwipe)
recognizers.append(leftSwipe)
//do the same for other recognizers
}
func leftSlide(recognizer:UISwipeGestureRecognizer){
print("Swipe")
}
//define other methods here to handle other recognizers...
override func willMove(from view: SKView) {
super.willMove(from: view)
for recognizer in recognizers {
self.view?.removeGestureRecognizer(recognizer)
}
recognizers.removeAll()
}
}
Upvotes: 1