Where am I leaking CGMutablePathRef in this code?
In my code I have CGMutablePathRef thePath = CGPathCreateMutable(); If I don't release it I literally get thousands of leaks because I'm doing the action constantly. However, if I do release it, my game eventually crashes. Any ideas? Is it possible I'm releasing it in the wrong place?
-(void)MoveObject:(int)Tag
{
representationX = gameViewObj.spaceshipImageView.center.x;
representationY = gameViewObj.spaceshipImageView.center.y;
CALayer *spaceshipLayer = gameViewObj.spaceshipImageView.layer;
shipAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath, NULL, representationX, representationY);
statusFire = YES;
BOOL parsedF = NO;
The remainder of the code is as follows:
-(void)MoveObj开发者_如何学JAVAect:(int)Tag
{
representationX = gameViewObj.spaceshipImageView.center.x;
representationY = gameViewObj.spaceshipImageView.center.y;
CALayer *spaceshipLayer = gameViewObj.spaceshipImageView.layer;
shipAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath, NULL, representationX, representationY);
statusFire = YES;
BOOL parsedF = NO;
if(Tag==LeftButtonTag)
{
gameViewObj.spaceshipImageView.transform = CGAffineTransformMakeRotation(M_PI + M_PI_2);
previousButtonTag = LeftButtonTag;
representationX--;
CGPathAddLineToPoint(thePath, NULL,representationX, representationY);
parsedF = YES;
}
else if(Tag==UpButtonTag)
{
gameViewObj.spaceshipImageView.transform = CGAffineTransformMakeRotation(0);
previousButtonTag = UpButtonTag;
representationY--;
CGPathAddLineToPoint(thePath, NULL,representationX, representationY);
parsedF = YES;
}
else if(Tag==RightButtonTag)
{
gameViewObj.spaceshipImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
previousButtonTag = RightButtonTag;
representationX++;
CGPathAddLineToPoint(thePath, NULL,representationX, representationY);
parsedF = YES;
}
else if(Tag==DownButtonTag)
{
gameViewObj.spaceshipImageView.transform = CGAffineTransformMakeRotation(M_PI);
previousButtonTag = DownButtonTag;
representationY++;
CGPathAddLineToPoint(thePath, NULL,representationX, representationY);
parsedF = YES;
}
if(parsedF){
shipAnimation.path = thePath;
shipAnimation.delegate = self;
shipAnimation.duration = 0.003;
[spaceshipLayer addAnimation:shipAnimation forKey:@"position"];
//To kill spaceship when moved backwards.
if(playField[representationX][representationY]==3){
[self doDie];
}
if(playField[representationX][representationY] == 2){
if(onSecretLine){
[gameViewObj.spaceshipImageView setCenter:CGPointMake(representationX, representationY)];
oldPositionX = representationX;
oldPositionY = representationY;
}
}
// case: breaking out
if (playField[representationX][representationY]==0){
if (onSecretLine){
if (statusFire)
{
availableOffline = YES;
oldPositionX=gameViewObj.spaceshipImageView.center.x;
oldPositionY=gameViewObj.spaceshipImageView.center.y;
[gameViewObj DrawLine];
onSecretLine = NO;
availableOffline = NO;
}
}
}
if (playField[representationX][representationY]==0)
if (!onSecretLine)
{
BOOL doIt=true;
// ------------------------------
// prevent contact own line
// ------------------------------
// left
if (Tag==LeftButtonTag) {
if (playField[representationX-1][representationY]==3) {
[self doDie];
doIt=false;
}
}
// right
if (Tag==RightButtonTag) {
if (playField[representationX+1][representationY]==3) {
[self doDie];
doIt=false;
}
}
// up
if (Tag==UpButtonTag) {
if (playField[representationX][representationY-1]==3) {
[self doDie];
doIt=false;
}
}
// down
if (Tag==DownButtonTag) {
if (playField[representationX][representationY+1]==3) {
[self doDie];
doIt=false;
}
}
// special things ...
if (doIt)
{
playField[representationX][representationY]=3;
[gameViewObj DrawLine];
}
}
// case: back to the secure line
if (playField[representationX][representationY]==2)
if (!onSecretLine)
{
[gameViewObj.spaceshipImageView setCenter:CGPointMake(representationX, representationY)];
availableOffline = NO;
onSecretLine = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:@"FindBirdCenter" object:nil];
for (int i=0; i<[gameViewObj.birdImageViewArray count]; i++) {
UIImageView* ImgBird=[gameViewObj.birdImageViewArray objectAtIndex:i];
int px=ImgBird.center.x;
int py=ImgBird.center.y;
// cristall point
playField[px][py]=5;
}
[self fillPlaygroundExtended];
//Elan function for filling area enclosed
[self fillAreaEnclosed:gameViewObj._myContext];
// invert ..
[self invertPlayground];
// turn the 3 into -> 20+
[self generateNewSecureLine];
}
if(Tag == UpButtonTag){
[self moveShipUp];
}
else if(Tag == RightButtonTag){
[self moveShipRight];
}
else if(Tag == DownButtonTag){
[self moveShipDown];
}
else if(Tag == LeftButtonTag){
[self moveShipLeft];
}
if(doScore == YES){
[self calculateScore];
doScore = NO;
}
[gameViewObj setNeedsDisplay];
}
}
You should perform a CGPathRelease() on your path after the line
shipAnimation.path = thePath;
as well as in an else statement for the
if(parsedF){
condition (otherwise it will still leak if parsedF
is NO.
You never release thePath
. At least not in that code snippet.
Core Graphics uses the Core Foundation Memory Rules, which you can read at Memory Management Programming Guide for Core Foundation
In short: Any function that contains Create
in its name will return a retained object that you will need to release with a function that Release
in it's name. In case of a CGPathRef
there is CGPathRelease
.
精彩评论