ios crash nsmutabledictionary sprite-kit skaction

ios - Spritekit se bloquea al ingresar al fondo



crash nsmutabledictionary (2)

Muy bien chicos, he estado desarrollando una aplicación en la que tengo un NSMutableDictionary con un objeto SKAction. El SKAction es para reproducir un sonido.

Todo esto funciona bien, excepto ... la aplicación falla al ingresar el fondo con la siguiente traza de la pila:

* thread #1: tid = 0x187d7, 0x3461b932 libGPUSupportMercury.dylib`gpus_ReturnNotPermittedKillClient + 10, queue = ''com.apple.spritekit.renderQueue, stop reason = EXC_BAD_ACCESS (code=1, address=0x1) frame #0: 0x3461b932 libGPUSupportMercury.dylib`gpus_ReturnNotPermittedKillClient + 10 frame #1: 0x3461c3d0 libGPUSupportMercury.dylib`gpusSubmitDataBuffers + 104 frame #2: 0x2eafc4a4 IMGSGX554GLDriver`SubmitPackets + 124 frame #3: 0x31f83cb0 GLEngine`gliPresentViewES + 168 frame #4: 0x31f8e136 OpenGLES`-[EAGLContext presentRenderbuffer:] + 62 frame #5: 0x002622e6 libglInterpose.dylib`EAGLContext_presentRenderbuffer(EAGLContext*, objc_selector*, unsigned int) + 370 frame #6: 0x323f9064 SpriteKit`-[SKView _renderContent] + 1220 frame #7: 0x3a90b0ae libdispatch.dylib`_dispatch_client_callout + 22 frame #8: 0x3a90f8f2 libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 26 frame #9: 0x323f8b72 SpriteKit`-[SKView renderContent] + 82 frame #10: 0x323f651a SpriteKit`__29-[SKView setUpRenderCallback]_block_invoke + 130 frame #11: 0x32418c86 SpriteKit`-[SKDisplayLink _callbackForNextFrame:] + 254 frame #12: 0x002615fe libglInterpose.dylib`-[DYDisplayLinkInterposer forwardDisplayLinkCallback:] + 270 frame #13: 0x321d7ad2 QuartzCore`CA::Display::DisplayLinkItem::dispatch() + 98 frame #14: 0x321d787c QuartzCore`CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 344 frame #15: 0x34dd476c IOMobileFramebuffer`IOMobileFramebufferVsyncNotifyFunc + 104 frame #16: 0x30a5ebe4 IOKit`IODispatchCalloutFromCFMessage + 248 frame #17: 0x2fd3cb80 CoreFoundation`__CFMachPortPerform + 136 frame #18: 0x2fd47776 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 34 frame #19: 0x2fd47712 CoreFoundation`__CFRunLoopDoSource1 + 346 frame #20: 0x2fd45ede CoreFoundation`__CFRunLoopRun + 1406 frame #21: 0x2fcb0470 CoreFoundation`CFRunLoopRunSpecific + 524 frame #22: 0x2fcb0252 CoreFoundation`CFRunLoopRunInMode + 106 frame #23: 0x349b72ea GraphicsServices`GSEventRunModal + 138 frame #24: 0x32565844 UIKit`UIApplicationMain + 1136 frame #25: 0x000bd1bc SpritekitCrash`main(argc=1, argv=0x27d4dc5c) + 116 at main.m:16

Como decía EXC_BAD_ACCESS, sospechaba de objetos zombies, pero habilitarlos en el esquema no ayudaba nada en la comprensión de este bloqueo.

Esto incluso ocurre en la configuración de proyecto más minimalista (literalmente 2 líneas de código) en MyScene.m:

self.arrSounds = [[NSMutableDictionary alloc] init]; [self.arrSounds setObject:[SKAction playSoundFileNamed:[NSString stringWithFormat:@"70.caf"] waitForCompletion:NO] forKey:[NSString stringWithFormat:@"1"]];

¿Cómo es esto posible?

Puede descargar este proyecto desde mi página de github: https://github.com/SabatinoMasala/SpritekitCrash


Bien, encontré el problema.

Detrás de escena, Spritekit usa AVAudioSession (lo cual tiene sentido) para [SKAction playSoundFileNamed:]

AVAudioSession no puede estar activo mientras la aplicación está en segundo plano, por lo que debemos detenerlo al pasar al fondo y reactivarlo al ingresar al primer plano.

Utilice este fragmento de código en applicationWillResignActive y applicationDidEnterBackground para deshabilitar la sesión AVAudioSession:

[[AVAudioSession sharedInstance] setActive:NO error:nil];

Para habilitarlo nuevamente, use esto en applicationWillEnterForeground:

[[AVAudioSession sharedInstance] setActive:YES error:nil];