A partire da iOS8 il mio gioco ha iniziato a bloccarsi all'improvviso. Dopo un po 'di debugging ho trovato che il gioco si blocca nelle due seguenti luoghi:iOS 8 SpriteKit si arresta in modo anomalo all'aggiunta o alla rimozione di un bambino dal blocco/dall'azione
[sparkNode runAction:[SKAction sequence:@[
//Some actions and finally...
[SKAction removeFromParent]]]]; // Crashes here (If I remove this action no crash occurs)
e il secondo posto:
[rankTransitionSprite runAction:[SKAction sequence:@[[SKAction scaleTo:1.5 duration:1.0],
[SKAction runBlock:^{
CGPoint rankPosition = _rankSprite.position;
[_rankSprite removeFromParent];
_rankSprite = [_spritesFactory spriteFromAtlasForImageName:[NSString stringWithFormat:@"rank%d", rank]];
[self addChild:_rankSprite]; // Crashes here
}],
[SKAction scaleTo:0.0 duration:1.0],
[SKAction removeFromParent]]]];
Su iOS 7.1 l'incidente non si verifica. Si blocca solo su iOS8. Per la prima caduta ho sostituito l'azione removeFromParent
con:
[SKAction runBlock:^{
dispatch_async(dispatch_get_main_queue(), ^{
[sparkNode removeFromParent];
});
}]
E questo sembra risolvere il problema.
Per il secondo crash ho fatto la stessa cosa (aggiungendo lo sprite nel thread principale) e lo schianto era sparito. log
Crash:
Thread 0 Crashed:: Dispatch queue: com.apple.spritekit.renderQueue
0 SpriteKit 0x000000010abed9fe SKCRenderer::preprocessSpriteImp(std::__1::vector<SKCRenderer::SpriteRenderInfo, std::__1::allocator<SKCRenderer::SpriteRenderInfo> >&, SKRenderQuadPool&, SKCSprite const*, _GLKMatrix4 const&, float, unsigned int&, bool) + 372
1 SpriteKit 0x000000010abee82b SKCRenderer::preprocessSpriteImp(std::__1::vector<SKCRenderer::SpriteRenderInfo, std::__1::allocator<SKCRenderer::SpriteRenderInfo> >&, SKRenderQuadPool&, SKCSprite const*, _GLKMatrix4 const&, float, unsigned int&, bool) + 4001
2 SpriteKit 0x000000010abee82b SKCRenderer::preprocessSpriteImp(std::__1::vector<SKCRenderer::SpriteRenderInfo, std::__1::allocator<SKCRenderer::SpriteRenderInfo> >&, SKRenderQuadPool&, SKCSprite const*, _GLKMatrix4 const&, float, unsigned int&, bool) + 4001
3 SpriteKit 0x000000010abe7c21 SKCRenderer::preprocessAndSubmitSpriteInternal(std::__1::vector<SKCRenderer::SpriteRenderInfo const*, std::__1::allocator<SKCRenderer::SpriteRenderInfo const*> >&, std::__1::vector<SKCRenderer::SpriteRenderInfo, std::__1::allocator<SKCRenderer::SpriteRenderInfo> >&, SKRenderQuadPool&, SKCSprite const*, _GLKMatrix4 const&) + 139
4 SpriteKit 0x000000010abeb7d1 SKCRenderer::submitScene(SKScene*, bool) + 393
5 SpriteKit 0x000000010abeff16 SKCRenderer::renderScene(SKScene*, bool) + 86
6 SpriteKit 0x000000010ab87542 -[SKView _renderContent] + 1027
7 libdispatch.dylib 0x000000010c974b94 _dispatch_client_callout + 8
8 libdispatch.dylib 0x000000010c9611e7 _dispatch_barrier_sync_f_invoke + 76
9 SpriteKit 0x000000010ab870f3 -[SKView renderContent] + 89
10 SpriteKit 0x000000010ab8415c __29-[SKView setUpRenderCallback]_block_invoke + 54
11 SpriteKit 0x000000010abb0a54 -[SKDisplayLink _callbackForNextFrame:] + 256
12 QuartzCore 0x000000010ecf0967 CA::Display::DisplayLinkItem::dispatch() + 37
13 QuartzCore 0x000000010ecf082f CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 315
14 CoreFoundation 0x000000010b39e4d4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
15 CoreFoundation 0x000000010b39e095 __CFRunLoopDoTimer + 1045
16 CoreFoundation 0x000000010b3613cd __CFRunLoopRun + 1901
17 CoreFoundation 0x000000010b3609f6 CFRunLoopRunSpecific + 470
18 GraphicsServices 0x000000010d41d9f0 GSEventRunModal + 161
19 UIKit 0x00000001098cb990 UIApplicationMain + 1282
E la mia domanda è: perché si pianta solo su iOS 8? (Su molti iOS 7.1 test non è mai caduto)
Non ho informazioni sulla causa principale, ma ho pensato di notare che un'altra buona soluzione per l'esempio 'removeFromParent' è di inserirla nel blocco di completamento di' runAction'. Come: '[nodo runAction: [SKAction fadeOutWithDuration: 1.0] completamento:^{[nodo removeFromParent]; }]; '. –
Penso che questo accada (almeno nel mio gioco) quando rimuovo una sprite in una collisione, e poi di kit sprite interna 'shouldCullNonVisibleNodes' cerca di rimuovere lo sprite, ma è già stato rimosso dalla memoria. Stavo sperimentando questo quando stavo rimuovendo i bambini dai loro genitori in caso di collisione, ma poi la collisione continuava a funzionare. '- (void) Arma: (Arma *) arma didCollideWithMonster: (mostro *) mostro { se (weapon.parent) { [arma removeFromParent]; } } Controllare se lo sprite ha un genitore prima di rimuoverlo, corretto questo mentre la collisione era in esecuzione più volte. –
Oh sì. Ho anche impostare 'skView.shouldCullNonVisibleNodes = false;' come gestisce la mia logica gioco tutta la rimozione di nodi. –