Running audio with SKAction is not reliable when it comes to interruptions which send your app into the background such as phone calls, pressing the home button, etc...
The solution is to use an AVAudioPlayer instead for anything other than short lived sound effects.
You would have to:
- Only use AVAudioPlayer for all your audio as it is designed and tested to handle interruptions.
- Use NSData as a sound container to be used with AVAudioPlayer (optional).
- Each sound should have its own temporary AVAudioPlayer instance for sound lifetime only.
There is a detailed explanation of how to do this on iKnowSomething.com which deals specifically with:
SpriteKit app using [SKAction playSoundFileNamed:] cause crash on app exit or going into background.
Deactivating AVAudioSession in AppDelegate applicationDidEnterBackground: fails with error (no deactivation in effect): Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)
SpriteKit app using [SKAction playSoundFileNamed:] on AVAudioSession interruption (e.g. call arrived) cannot be reactivated (silence).
How to implement AVAudioPlayer in place of SpriteKit [SKAction playSoundFileNamed:]?
LearnCocos2D also wrote an excellent answer on the issue of preventing crashes when an app goes into the background and an AVAudioPlayer is being used.
#import <AVFoundation/AVFoundation.h>
...
- (void)applicationWillResignActive:(UIApplication *)application
{
// prevent audio crash
[[AVAudioSession sharedInstance] setActive:NO error:nil];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// prevent audio crash
[[AVAudioSession sharedInstance] setActive:NO error:nil];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// resume audio
[[AVAudioSession sharedInstance] setActive:YES error:nil];
}
His original answer is here.