2

After profiling my app, I appear to have a memory leak somewhere in this method:

- (void) didEvaluateActions {
for (int x = 0; x < self.children.count; x++) {
    if ([self.children[x] isKindOfClass:[BallNode class]]) {
        BallNode * ball = (BallNode *) self.children[x];

        if (abs(ball.physicsBody.velocity.dx) < BALL_MIN_VEL_X) {
            ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MIN_VEL_X, ball.physicsBody.velocity.dy);
        }

        if (abs(ball.physicsBody.velocity.dx) > BALL_MAX_VEL_X) {
            ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MAX_VEL_X, ball.physicsBody.velocity.dy);
        }

        if (abs(ball.physicsBody.velocity.dy) < BALL_MIN_VEL_Y) {
            ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MIN_VEL_Y);
        }

        if (abs(ball.physicsBody.velocity.dy) > BALL_MAX_VEL_Y) {
            ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MAX_VEL_Y);
        }
    }
}
}

instruments I'm not seeing where this method could be causing a memory leak. BallNode is not created here, so why is instruments pointing back to this location? How is this method causing a leak?

-Thank in advance

sangony
  • 11,636
  • 4
  • 39
  • 55
Jake
  • 13,097
  • 9
  • 44
  • 73
  • I had the same issue and solved by "skView.showsPhysics = false". Showing the physic's bodies causes a memory leak. – salocinx Jun 28 '16 at 14:13

2 Answers2

2

I it doesn't appear that you are doing anything wrong, but if you are pointing the the correct spot in code then I think it has to do with self.children.count

Try

NSUInteger count = self.children.count;

for (NSInteger x = 0; x < count; x++)
{
    if ([self.children[x] isKindOfClass:[BallNode class]]) {
        BallNode * ball = (BallNode *) self.children[x];

        if (abs(ball.physicsBody.velocity.dx) < BALL_MIN_VEL_X) {
            ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MIN_VEL_X, ball.physicsBody.velocity.dy);
        }

        if (abs(ball.physicsBody.velocity.dx) > BALL_MAX_VEL_X) {
            ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MAX_VEL_X, ball.physicsBody.velocity.dy);
        }

        if (abs(ball.physicsBody.velocity.dy) < BALL_MIN_VEL_Y) {
            ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MIN_VEL_Y);
        }

        if (abs(ball.physicsBody.velocity.dy) > BALL_MAX_VEL_Y) {
            ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MAX_VEL_Y);
        }
    }
}

The way you have it currently it is trying to evaluate self.children.count every iteration through the loop. This shouldn't cause a leak, but there could be something under the hood preventing it from being released correctly when evaluating it repeatedly.

Also you may want to look at enumerateChildNodesWithName: as a quicker alternative than looking at every child and seeing if it is a BallNode.

Hopefully that is the issue and is easily fixed.

Skyler Lauren
  • 3,792
  • 3
  • 18
  • 30
1

You keep creating more and more instances of your BallNode class. Try adding ball = nil; after your last if statement but honestly I do not know if that will help you.

Either your code logic is wrong or there is other stuff going on which you did not post. Usually it would make sense for you to have an ivar of your ball which you would apply the posted code to.

sangony
  • 11,636
  • 4
  • 39
  • 55
  • I have to object that. BallNode * ball = (BallNode*)self.children[x] is simply casting the child at index x to a BallNode. In itself this doesn't allocate any new objects. – Shirkrin Oct 23 '15 at 11:52