Sprite Kit iOS 7.1 crash on removeFromParent

I have updated iPad Air to 7.1 and Xcode to 5.1. Xcode wanted to update my project to recommended settings, I agreed.

After that my game began crashing in a couple of places when I remove node from parent.

That was a surprise for me — there were no crossings before the update. I restored my project and found out what Xcode does to it — only changes Architectures string:

Before: Architectures before update

After: Architectures after update

In the old version there are no crashes. There are no crashes if I remove arm64 support in new version. In the simulator there are no crashes in both new and old versions.

Where should I pay attention in my code?

Code stack:

SpriteKit`SKCSprite::removeSubsprite(SKCSprite*):
0x1859442cc:  stp    fp, lr, [sp, #-16]!
0x1859442d0:  add    fp, sp, 0
0x1859442d4:  stp    x20, x19, [sp, #-16]!
0x1859442d8:  sub    sp, sp, #16
0x1859442dc:  mov    x19, x0
0x1859442e0:  str    x1, [sp, #8]
0x1859442e4:  add    x20, sp, 8
0x1859442e8:  add    x0, x19, 544
0x1859442ec:  mov    x1, x20
0x1859442f0:  bl     0x18594872c               ; unsigned long std::__1::__tree<SKCSprite*, std::__1::less<SKCSprite*>, std::__1::allocator<SKCSprite*> >::__erase_unique<SKCSprite*>(SKCSprite* const&)
0x1859442f4:  add    x0, x19, 464
0x1859442f8:  mov    x1, x20
0x1859442fc:  bl     0x185948218               ; std::__1::list<SKCSprite*, std::__1::allocator<SKCSprite*> >::remove(SKCSprite* const&)
0x185944300:  ldr    x20, [sp, 1]
0x185944304:  ldrb   w8, [x20, #18]
0x185944308:  ldrh   w9, [x20, #16]
0x18594430c:  orr    w8, w9, w8, lsl #16
0x185944310:  tbnz   w8, #1, 0x185944324       ; SKCSprite::removeSubsprite(SKCSprite*) + 88
0x185944314:  ldr    x9, [x20, 61]
0x185944318:  ldr    x9, [x9, 2]
0x18594431c:  cbnz   x9, 0x185944324           ; SKCSprite::removeSubsprite(SKCSprite*) + 88
0x185944320:  tbz    w8, #8, 0x185944330       ; SKCSprite::removeSubsprite(SKCSprite*) + 100
0x185944324:  mov    x0, x19
0x185944328:  mov    x1, x20
0x18594432c:  bl     0x18594828c               ; SKCSprite::removeFromOffscreenList(SKCSprite*)
0x185944330:  str    xzr, [x20, #392]
0x185944334:  ldr    x8, [x20, 0]
0x185944338:  ldr    x8, [x8, 10]
0x18594433c:  mov    x0, x20
0x185944340:  blr    x8
0x185944344:  ldrh   w8, [x19, #20]
0x185944348:  orr    w9, w8, #0x40
0x18594434c:  strh   w9, [x19, #20]
0x185944350:  ldr    x8, [x19, 49]
0x185944354:  cbz    x8, 0x185944388           ; SKCSprite::removeSubsprite(SKCSprite*) + 188
0x185944358:  add    x9, x19, 392
0x18594435c:  ldrh   w10, [x8, #20]
0x185944360:  orr    w10, w10, #0x40
0x185944364:  strh   w10, [x8, #20]
0x185944368:  ldr    x8, [x9, 0]
0x18594436c:  add    x9, x8, 392
0x185944370:  ldrh   w10, [x8, #20]
0x185944374:  orr    w10, w10, #0x40
0x185944378:  strh   w10, [x8, #20]
0x18594437c:  ldr    x8, [x8, 49]
0x185944380:  cbnz   x8, 0x18594435c           ; SKCSprite::removeSubsprite(SKCSprite*) + 144
0x185944384:  ldrh   w9, [x19, #20]  EXC_BAD_ACCESS here.
0x185944388:  orr    w8, w9, #0x2
0x18594438c:  strh   w8, [x19, #20]
0x185944390:  b      0x185944398               ; SKCSprite::removeSubsprite(SKCSprite*) + 204
0x185944394:  ldrh   w8, [x19, #20]
0x185944398:  tbnz   w8, #7, 0x1859443ac       ; SKCSprite::removeSubsprite(SKCSprite*) + 224
0x18594439c:  orr    w8, w8, #0x80
0x1859443a0:  strh   w8, [x19, #20]
0x1859443a4:  ldr    x19, [x19, 49]
0x1859443a8:  cbnz   x19, 0x185944394          ; SKCSprite::removeSubsprite(SKCSprite*) + 200
0x1859443ac:  sub    sp, fp, #16
0x1859443b0:  ldp    x20, x19, [sp], #16
0x1859443b4:  ldp    fp, lr, [sp], #16
0x1859443b8:  ret    lr

UPDATE: New information:

My error:

Error

Stack:

Call stack

I found out something wrong. My node I want to remove consists of two SKSpriteNodes (my sprite image and its shadow) and one SKShapeNode (a thin black rope). I tried to replace my SKShapeNode rope with a SKSpriteNode rope and I got success — problem gone.

Code to remove my node from parent:

SKAction *moveCloud = [SKAction moveToX:destinationX duration:moveDuration];
[cloud runAction:moveCloud completion:^{
    [cloud removeFromParent];
}];

Code to add a SKShapeNode rope to my node:

- (void)addRopeToCloud:(SKNode *)cloud
{
    CGFloat maxY = self.scene.size.height;
    CGFloat length = maxY - [self.scene convertPoint:cloud.position fromNode:cloud.parent].y;

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, 0);
    CGPathAddLineToPoint(path, NULL, 0, length);

    SKShapeNode *rope = [[SKShapeNode alloc] init];
    rope.path = path;
    rope.strokeColor = [UIColor blackColor];
    rope.lineWidth = 0.1;
    rope.antialiased = YES;
    rope.zPosition = -0.01;

    CGFloat threadScale = 1 / cloud.xScale;

    rope.xScale = threadScale;
    rope.yScale = threadScale;

    [cloud addChild:rope];
    CGPathRelease(path);
}

Code to add a SKSpriteNode rope to my node, that resolves the problem:

- (void)addRopeToCloud:(SKNode *)cloud
{
    CGFloat maxY = self.scene.size.height;
    CGFloat length = maxY - [self.scene convertPoint:cloud.position fromNode:cloud.parent].y;

    CGSize ropeSize = CGSizeMake(1.5, length);
    SKSpriteNode *rope = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:ropeSize];
    rope.anchorPoint = CGPointMake(0.5, 0);

    CGFloat ropeScale = 1 / cloud.xScale;
    rope.xScale = ropeScale;
    rope.yScale = ropeScale;

    rope.zPosition = -0.01;

    [cloud addChild:rope];
}

It looks like something wrong in my SKShapeNode adding code, but I can't understand what exactly is.


It seems to only happen on iOS 7.1. Not sure if it is an Apple bug, but this seems to fix it:

- (void)removeFromParent
{
    [self.aShapeNode removeFromParent];
    self.aShapeNode = nil;

    [super removeFromParent];
}

You can call this method before you dealloc (or present new scene) the SKShapeNodes

- (void)cleanUpChildrenAndRemove:(SKNode*)node {
    for (SKNode *child in node.children) {
        [self cleanUpChildrenAndRemove:child];
    }
    [node removeFromParent];
}

I had the same problem but that solved it. My original question:

SKShapeNode producing crash sometimes on dealloc EXC_BAD_ACCESS


I also crash with SKShapeNode when its parent remove from superview in iOS 7.1

My work around is set SKShapeNode property to nil before it remove from parent


Not sure if my situation exactly mimics yours, but I was getting the same error (with the same stack trace) and realized that I had set up two classes that were each keeping the SKShapeNode object as properties. I'm pretty sure that when I called removeFromParent to remove object node in ClassA the object was deallocated. Then, in ClassB, I called self.node = aNewNode (keep in mind that the object that self.node pointed to had been deallocated), the auto-synthesized setter tried to de-allocate node for a second time.

I thought ARC was supposed to keep track of all this, but the bug is very sporadic so I'm honestly not 100% sure what's going on. I have an SKSpriteNode with the same pattern and I have never seen it causing this error. My fix right now has been to make the ClassB property weak, so it's not a problem if self.node has already been deallocated. Hope that helps!