Program crashes when function called multiple times

251 Views Asked by At

I have a function that moves a SKSpriteNode from one point to another. It works fine when I call it once. But when I call it multiple times, the whole program crashes.

    func play()
    {
        self.moveNode()
        self.moveNode()
    }

    func moveNode()
    {
        let player = SKSpriteNode(imagenamed: "player.png")
        player.position = CGPointMake(500.0, 500.0)
        self.addChild(player)
        let fire = SKAction.moveTo(CGPointMake(100.0, 100.0), duration: 0.25)
        player.runAction(fire)
    }

These are the crash logs,( I don't know how to read them so I'm posting everything, I ran it like 5-6 times):

2015-06-15 20:55:49.616 The Game[2099:42388] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: name:'(null)' texture:[ 'player.png' (640 x 480)] position:{500, 500} size:{64, 48} rotation:0.00' * First throw call stack: ( 
0 CoreFoundation 0x0000000101bc6a75 exceptionPreprocess + 165 
1 libobjc.A.dylib 0x00000001038d4bb7 objc_exception_throw + 45 
2 CoreFoundation 0x0000000101bc69ad +[NSException raise:format:] + 205 
3 SpriteKit 0x00000001024881a6 -[SKNode addChild:] + 111 
4 The Game 0x00000001019d2156 _TFC13The_Game6Level111createNodefS0_FT_T_ + 678 
5 The Game 0x00000001019d21fb _TFC13The_Game6Level110moveNodefS0_FT_T_ + 59 
6 The Game 0x00000001019d0bc9 _TFC13The_Game6Level16updatefS0_FSdT_ + 73 
7 The Game 0x00000001019d0c08 _TToFC13The_Game6Level16updatefS0_FSdT_ + 40 
8 SpriteKit 0x000000010247bb68 -[SKView(Private) _update:] + 1106 
9 SpriteKit 0x00000001024792d9 -[SKView renderCallback:shouldBlock:] + 837 
10 SpriteKit 0x0000000102476391 __29-[SKView setUpRenderCallback]_block_invoke + 56 
11 SpriteKit 0x00000001024a2df4 -[SKDisplayLink _callbackForNextFrame:] + 256 
12 QuartzCore 0x000000010652a5c7 _ZN2CA7Display15DisplayLinkItem8dispatchEv + 37 
13 QuartzCore 0x000000010652a48f _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 315 
14 CoreFoundation 0x0000000101b2e6c4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 20 
15 CoreFoundation 0x0000000101b2e285 __CFRunLoopDoTimer + 1045 
16 CoreFoundation 0x0000000101af159d __CFRunLoopRun + 1901 
17 CoreFoundation 0x0000000101af0bc6 CFRunLoopRunSpecific + 470 
18 GraphicsServices 0x0000000108fc6a58 GSEventRunModal + 161 
19 UIKit 0x000000010260f580 UIApplicationMain + 1282 
20 The Game 0x00000001019d872e top_level_code + 78 
21 The Game 0x00000001019d876a main + 42 
22 libdyld.dylib 0x00000001040c2145 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)
2

There are 2 best solutions below

0
On BEST ANSWER

It's really a bad idea to use animation by calling methods that way. Here is a way to do the same thing with sequenced and repeated actions wrapping the basic commands:

let move = SKAction.moveTo(CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)), duration: 0)
let fire = SKAction.moveTo(CGPointMake(100.0, 100.0), duration: 0.25)
let wait = SKAction.waitForDuration(0.5)

let sequence = SKAction.sequence([move, fire, wait])
let repeated = SKAction.repeatAction(sequence, count:2)

player.runAction(repeated)
1
On

The problem is that your code is calling addChild to your player node even though it has a parent already.

In your code, moveNode, you call self.addChild(player) everytime you run moveNode. That will crash the game if you run that function more than once.

The solution is to initialize your node in another function that is called only once, or either run a condition check to prevent the code from running the addChild function more than once.