4

I have a sprite-kit game scene (SKScene) that uses audio clips from time to time. I don't want to create a new action (SKAction) every time I need to run a short audio clip since the sound could stutter. So I initialize an action variable with a file name and get ready to use it when necessary.

class GameScene: SKScene {
    let audioMatchAction = SKAction.playSoundFileNamed("myAudio", waitForCompletion: false)
}

Then when I need to run this audio clip, I just use the following line of code.

self.run(audioMatchAction)

Considering all circumstances, there are some indications that the memory might be leaking when the view controller (UIViewController) sets a scene. So I've used Allocations to see what's going on. And it says that there are two leaks pointing to the AudioToolbox library. Anyway, I've changed the line above to the following.

let waitAction = SKAction.wait(forDuration: 1.0)
self.run(audioMatchAction, withKey: "audio")
self.run(waitAction, completion: {
    self.removeAction(forKey: "audio")
})

Allocations still says that there are two leaks when the app transitions to the game view controller. I've read a few dozen topics regarding SKAction and audio clips. There are some topics where they suggest that we use SKAudioNode as opposed to SKAction.playSoundFileNamed. I've tried that. And the leaks remain. I've even used AVAudioPlayer. I still have two leaks. If I stop calling audio clips altogether, Allocations won't report a leak, which tells me that use of these clips are causing the leaks. So what can I do to stop audio clips from leaking memory? Thanks.

UPDATE

I think I used the following lines of code for AVAudioPlayer yesterday to see if the leaks would disappear.

class GameScene: SKScene {
    let audioURLMatch = URL(fileURLWithPath: Bundle.main.path(forResource: "myAudio", ofType: "caf")!) as NSURL
    var audioURLMatchPlayer = AVAudioPlayer()
    override func didMove(to view: SKView) {
        // audio //
        do {
            audioURLMatchPlayer = try AVAudioPlayer(contentsOf: audioURLMatch as URL)
            audioURLMatchPlayer.prepareToPlay()
        } catch let error {

        }
    }
}

enter image description here

El Tomato
  • 6,479
  • 6
  • 46
  • 75
  • Possible duplicate of http://stackoverflow.com/questions/21022433/skaction-playsoundfilenamed-failed-at-500-mp3, where it is suggested that you use AVAudioPlayer instead. Okay, you say you've done that but it would be good if you'd show the code, since I use AVAudioPlayer and I assure you it doesn't leak if handled correctly. – matt May 07 '17 at 01:42
  • @matt Thanks for the comment. I don't remember the exact code, but I do remember referring to the folllowing article. https://dzone.com/articles/using-avfoundation-to-play-audio-in-an-skaction-in – El Tomato May 07 '17 at 02:04

1 Answers1

0

For future reference, declaring audioURLMatchPlayer as a type instead of instantiating the player will prevent the memory leak.

Use var audioURLMatchPlayer: AVAudioPlayer? instead of var audioURLMatchPlayer = AVAudioPlayer()