11 Replies
      Latest reply on Jun 13, 2018 9:00 PM by artie
      JShen26 Level 1 Level 1 (0 points)

        I'm posting this because no one seems to discover this problem in iOS9, but it is critical.

        The problem is simple, every time you call

         

        sprite.runAction(SKAction.playSoundFileNamed("sound.wav", waitForCompletion: false))


        a little bit of memory leaks.


        It might not be such a big issue at first, but it will eventually slow down your games since the memory will NEVER be recycled.


        Reproducing this bug is easy, just call this method in scene's update function, and you can watch it eating up all your memory.


        The solution is simple too, replace the code with the new SKAudioNode for iOS9 and up, and you are good to go.


        I Think this is one thing everyone should try first to repair one's game for iOS9.

         

        • Re: Big memory leak in iOS9 with playSoundFileNamed
          hmexx Level 1 Level 1 (0 points)

          I just noticed it as well. Thought I had fixed/worked-around all the ios9 issues.

           

          Funny, all I have to do is keep clicking on a button (click sound effect) and I can use up several MB in seconds.

           

          I've been working through this and using SKAudioNode wherever possible, but because the API is so different, it's not a straightforward switch. Some SFX actions I have are burried deep in sequences and groups of SKActions.

           

          I'll probably leave a few leaks in there, unfortunately.

          • Re: Big memory leak in iOS9 with playSoundFileNamed
            kertrats Level 1 Level 1 (0 points)

            I agree.  Now can anyone elucidate me on the exact fix?

            I have been fiddling with SKAudioNode for a couple hours and can't seem to figure out how to exactly replace

             

            sprite.runAction(SKAction.playSoundFileNamed("sound.wav", waitForCompletion: false))
            

             

            with an SKAudioNode equivalent.

             

            Thanks for any help.  ANDY

              • Re: Big memory leak in iOS9 with playSoundFileNamed
                Fuzzygoat Level 1 Level 1 (20 points)

                As the previous poster pointed out the API for SKAudioNode works in a different way from SKAction.playSoundFileNamed: The main difference being that SKAudioNode is an actual node (that has a position etc.) so to get a sound out of it you need to do three things:

                 

                1. Initialise the SKAudioNode with a sound file
                2. Add it to the scene, either directly or as a child
                3. Run an SKAction.play() action on it to trigger it to play

                 

                    func testAudioNode() {
                        let audioNode = SKAudioNode(fileNamed: "LevelUp")
                        audioNode.autoplayLooped = false
                        self.addChild(audioNode)
                        let playAction = SKAction.play()
                        audioNode.runAction(playAction)
                    }
                
                

                 

                I am guessing that if you have a sprite game character that you wanted to add sounds to you could create an SKAudioNode for each sound and then parent them to the character SKSpriteNode. You could then access each sound by searching for its node or if you use a custom SKSpriteNode subclass you could add weak var properties to store pointers to each sound.

                 

                    func setupSprite() -> SKSpriteNode {
                        let spriteNode = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 50, height: 50))
                        spriteNode.position = CGPoint(x: 25, y: 25)
                        let audioNode = SKAudioNode(fileNamed: "alert")
                        audioNode.name = "ALERT_SOUND"
                        audioNode.autoplayLooped = false
                        spriteNode.addChild(audioNode)
                        self.addChild(spriteNode)
                        return spriteNode
                    }
                  
                    func moveSpritePlaySound(sprite: SKSpriteNode) {
                        let moveAction = SKAction.moveToY(600, duration: 4)
                        let soundAction = SKAction.runBlock { () -> Void in
                            if let soundNode = sprite.childNodeWithName("ALERT_SOUND") {
                                let playAction = SKAction.play()
                                soundNode.runAction(playAction)
                            }
                        }
                        let sequence = SKAction.sequence([moveAction, soundAction])
                        sprite.runAction(sequence)
                    }
                
                

                 

                There are probably better ways, but this is essentially how it works.

                 

                Gary.

                  • Re: Big memory leak in iOS9 with playSoundFileNamed
                    kertrats Level 1 Level 1 (0 points)

                    Thanks.  Yeah, now I 'get' it....

                    I was looking for a one on one fix for that specific line of code...

                    Anyway, you have set me on the path of understanding.  LOL

                    Appreciate it.

                    • Re: Big memory leak in iOS9 with playSoundFileNamed
                      greven Apple Staff Apple Staff (70 points)

                      Hi Fuzzygoat,

                       

                      Thanks for pointing that out to folks. SKAudioNode is a much more complicated and powerful node than the playSound SKAction. If you find any problems please don't hesitate to file a radar. Even if communication back isn't stellar we do look at them all.

                       

                      Cheers

                        • Re: Big memory leak in iOS9 with playSoundFileNamed
                          cbuck12000 Level 1 Level 1 (0 points)

                          Hi!

                           

                          I think I am running into this memory leak too.  I am using iOS 10, Swift 3, and SpriteKit.  After playing my game for a while, it starts losing the ability to get other resources (sprites, etc).  When I turn off the sound effects in my game (through my own config dialog), I don't see the issue.  I also noticed that after a while, XCode reports that it can't play the sound because the resource was not found and when it nears a crash, I get "too many files open".  My conclusion is that I am running into the same issue reported on this post.

                           

                          To play sound effects I use:  _sprite.runAction(SKAction.playSoundFileNamed("sound.mp3", waitForCompletion: false))

                           

                          Question 1:  Is there a fix for this?  If so, how can I get it?  This is a huge issue that is holding me up.

                          Question 2:  If no fix, are you stating that we should use the SKAudioNode for simple repeated sound effects?  I am using it for the background music.

                           

                          Thank you in advance,

                           

                           

                          Craig

                            • Re: Big memory leak in iOS9 with playSoundFileNamed
                              cbuck12000 Level 1 Level 1 (0 points)

                              Update:  I was able to resolve this issue with the following:

                               

                              1)  Updated the code to call the sound action on individual sprites and not on the main Scene.  This greatly improved the ability to get resources as time progressed.  Doing this, I no longer had missing sprites or other resources, but once in a while, the sound would stop and later recover.  I found that this was a different bug that was reported.

                               

                              2)  Updated to XCode 8.2 which was recently released.  Apple fixed the issue where sound would cut out and then recover when sound effects were played in quick succession.

                               

                              Just providing some informatoin to help others.

                              Thanks!

                      • Re: Big memory leak in iOS9 with playSoundFileNamed
                        ultraviolet Level 1 Level 1 (0 points)

                        Any news about this ? I guess it is still the issue. The thing is that even SKAudioNode is broken in some situations:

                         

                        http://stackoverflow.com/questions/35662139/skaudionode-crashes-when-pluggin-in-out-headphones

                         

                        And SKAudioNode requires deployment target set to 9.0 so, not a great workaround.

                         

                        Using AVAudioPlayer to play short sounds is not an option as well due to performance reasons ...

                         

                        Currently, it seems that there is nothing useful for playing short sounds in SpriteKit...

                         

                        @greven

                         

                        Any useful tips / ideas / news ?

                        • Re: Big memory leak in iOS9 with playSoundFileNamed
                          vzlotskiy Level 1 Level 1 (10 points)

                          Same thing happens in iOS 10 beta. Will it ever get fixed?

                          • Re: Big memory leak in iOS9 with playSoundFileNamed
                            artie Level 1 Level 1 (0 points)

                            Looks like Apple does not care of developer exprience for years. Several moths of building the game just stuck at this (4th day already).