Group Group Group Group Group Group Group Group Group

DropCharge causing memory leak

I make the DropCharge game by following the book. After I finish, I go ahead and check the memory pane of the Debug Navigator, I found out that the memory is constantly going higher and higher every time, and when the game is over, pressing restart to open a new scene doesn’t free up any memory. Seems like something is making a retain cycle. Any idea or running into similar issue? Thanks.

While you’re in the simulator you will be emulating the 3D hardware in the phone and even on a fast Mac that can cause some serious performance issues. Give it a try on the actual hardware… I was amazed at how slow and how much memory was being consumed when trying some SpriteKit programming on the simulator, in fact I thought my app had serious issues where in fact it was fine.

There is memory leak because we don’t remove the off screen background node and the foreground overlays.

Found it yesterday and fixed like this:

func isOffScreen(node: SKNode) -> Bool {
    var isOffScreen = false
    
    let cameraPos = self.getCameraPosition()
    if node.position.y + self.backHeight < cameraPos.y {
        isOffScreen = true
    }
    
    return isOffScreen
}

func removeOffScreenBackgroundNode() {
    bgNode.enumerateChildNodesWithName("Overlay") { (node, _) -> Void in
        if self.isOffScreen(node) {
            node.removeFromParent()
        }
    }
}

func removeOffscreenOverlayNode() {
    for node in fgNode.children {
        if isOffScreen(node) {
            node.removeFromParent()
        }
    }
}

As of june 2020, swift 5 iOS 13.5, I have updated the method “updateLevel” based on @ivanchenhz solution. When overlays are added in the scene, check every “Overlay” nodes out of camera and remove them. I am quite new to swift so please let me know if this is the wrong way to “fix” the issue.

First, let’s see the issue :

  • set to true view.showsFPS and view.showsNodeCount in GameViewController.swift
  • set an insane amount of gain in setPlayerVelocity(_: ) to very quickly add new layers
func setPlayerVelocity(_ amount:CGFloat) 
{
 let gain: CGFloat = 100
 player.physicsBody!.velocity.dy = max(player.physicsBody!.velocity.dy, amount * gain)
}

Quickly, the amount of nodes is above 10K, 15K, 20K, too much K and FPS goes from 60fps to almost 0

Now, let’s remove nodes not needed anymore since they will never be visible again

func updateLevel() 
{
 let cameraPos = camera!.position
 if cameraPos.y > levelPositionY - size.height 
 {
  createBackgroundOverlay()
  while lastOverlayPosition.y < levelPositionY 
  { 
   addRandomForegroundOverlay() 
  }

  // Start fix here, remove off screen nodes
  enumerateChildNodes(withName: "//Overlay")
  {
   [weak self] node, _ in
   guard let self = self else { return }

   let cameraPos = self.camera!.position
   if node.position.y + self.backgroundOverlayHeight < cameraPos.y
   {
    node.removeFromParent()
   }
  }
 // End fix 
 }
}

Now, the nodes count stay in an acceptable range 150…250 and FPS stay at 60fps

I hope it can be of any help.

And when you read further the latest book version (as of june 2020), you have the required code to address the issue at the end of chapter 17 section IV. I might have read the whole chapter before trying to fix the issue by myself :stuck_out_tongue:

// remove old foreground nodes...
for fgChild in fgNode.children {
  let nodePos = fgNode.convert(fgChild.position, to: self)
  if !isNodeVisible(fgChild, positionY: nodePos.y) {
    fgChild.removeFromParent()
  }
}

@mokhet Thank you for sharing this - much appreciated!

Hi…I’m additionally encoutering this equivalent memory spill. For my situation CGDataProviderCreateWithCopyOfData is made everytime I take pictures with my photograph application. This article will at that point endure in memory after I take various photographs until I get an out of memory blunder. In the event that I utilize the “Holes” Xcode Instrumentation apparatus, it focuses to AVCapturePhotoOutput - init similar to the wellspring of the memory spill. I’m utilizing xcode 12 beta 3/4 however I’ve likewise given this a shot a couple of different adaptations of iOS and I get a similar outcome (ie iOS 10.2, 11.4, 12 b3). Would you be able to if it’s not too much trouble, direct me toward a guide that would help in settling this.