开发者

Unable to stop memory leak

I am trying to teach myself Objective-c. I have many books, all of which I have read to try to fix my problem. I am drawing myself a map with the following code.

-(void)drawMap
{
    for (NSInteger tempY=character.locationY-5;tempY<character.locationY+6;tem开发者_StackOverflowpY++)
    {
        for (NSInteger tempX=character.locationX-4;tempX<character.locationX+5;tempX++)
        {
            MapTile *a = [[MapTile alloc] initWithFrame:CGRectMake
                            (((tempX-(character.locationX-3)) * 44)+6,
                            ((tempY-(character.locationY-5)) * 44)-12,0,0)
                            :[map getTilePic:tempY:tempX]];
            [self.view addSubview:a];
        }
    }
    CharacterTile *a = [[CharacterTile alloc] initWithFrame:CGRectMake(138,206,0,0)]; 
    [self.view addSubview:a];
}

And my MapTile looks like this -

-(id)initWithFrame:(CGRect)frame :(NSInteger)pictureNumber
{
    if (!dungeonLoaded)
    {
        UIImage *tempImage;
        for (NSInteger count=0;count<54;count++)
        {
            NSString *temp = [NSString alloc];
            temp = [NSString stringWithFormat:@"%i.png", count];
            tempImage = [UIImage imageNamed:temp];
            loadedImage[count] = tempImage;
        }
        dungeonLoaded = YES;
    }
    CGRect rect = CGRectMake(frame.origin.x,frame.origin.y,
                             loadedImage[pictureNumber].size.width,
                             loadedImage[pictureNumber].size.height);
    self = [super initWithFrame:rect];
    image = [loadedImage[pictureNumber] retain];
    self.opaque = NO;
    self.backgroundColor = [UIColor clearColor];
    return self;
}

My problem is that if I move around the map for a while, only this is the only method that is called and it slows down considerably after only a dozen or so moves.

I originally had the maptile images load each time I moved and thought that this might be the problem, so have changed it, as you can see, to only load the pictures once and re-use them. I tried using an imagecache from the book "Beginning Iphone game development" and emptying the cache at the start of each drawmap method. I tried inplementing an autorelease pool and loading the tiles with the autorelease tag. I tried deallocating the tiles as they were drawn, but as you would expect, this destroyed the image on the screen and therefore the map wasnt visible.

I am not lazy and have tried extensively to get this to stop slowing down, but unfortunately, it is beyond my coding skills at this time.

Any help would be greatly appreciated.

Thanks in advance.

Adam


There are a number of issues:

  1. You alloc a number of MapTile instances each time that you draw the map, but you never release them.

  2. You alloc a CharacterTile instance each time that you draw the map, and you never release it.

  3. Your MapTile constructor allocates an NSString instance that is never released.

  4. Your MapTile constructor calls retain on loadedImage[pictureNumber], but there is no matching release.

  5. You add MapTile and CharacterTile instances to the view repeatedly, but your code doesn't remove previous instances from the view.

So 1-4 are bad, but I would bet that it's #5 that is killing your performance. You're accumulating more and more subviews each time you update the map, and never removing your old tiles from the view. Your code is piling the new tiles on top of the old, and the bigger the pile gets, the slower your app is going to run.

In any case, this should fix issues 1-3:

-(void)drawMap
{
    for (NSInteger tempY=character.locationY-5;tempY<character.locationY+6;tempY++)
    {
        for (NSInteger tempX=character.locationX-4;tempX<character.locationX+5;tempX++)
        {
            MapTile *a = [[MapTile alloc] initWithFrame:CGRectMake
                            (((tempX-(character.locationX-3)) * 44)+6,
                            ((tempY-(character.locationY-5)) * 44)-12,0,0)
                            :[map getTilePic:tempY:tempX]];
            [self.view addSubview:a];
            [a release];
        }
    }
    CharacterTile *a = [[CharacterTile alloc] initWithFrame:CGRectMake(138,206,0,0)]; 
    [self.view addSubview:a];
    [a release];
}

-(id)initWithFrame:(CGRect)frame :(NSInteger)pictureNumber
{
    if (!dungeonLoaded)
    {
        UIImage *tempImage;
        for (NSInteger count=0;count<54;count++)
        {
            NSString* temp = [NSString stringWithFormat:@"%i.png", count];
            tempImage = [UIImage imageNamed:temp];
            loadedImage[count] = tempImage;
        }
        dungeonLoaded = YES;
    }
    CGRect rect = CGRectMake(frame.origin.x,frame.origin.y,
                             loadedImage[pictureNumber].size.width,
                             loadedImage[pictureNumber].size.height);
    self = [super initWithFrame:rect];
    image = [loadedImage[pictureNumber] retain];  //FIXME:  you need to release this somewhere
    self.opaque = NO;
    self.backgroundColor = [UIColor clearColor];
    return self;
}

Issues 4-5 you'll have to work out for yourself. But if you just update drawMap so that it removes all the subviews before adding any new ones, I think you'll be most of the way there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜