无法阻止内存泄漏

时间:2011-05-04 02:02:00

标签: objective-c memory-management memory-leaks

我正在努力教自己Objective-c。我有很多书,我读过这些书都试图解决我的问题。我正在使用以下代码绘制自己的地图。

-(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];
        }
    }
    CharacterTile *a = [[CharacterTile alloc] initWithFrame:CGRectMake(138,206,0,0)]; 
    [self.view addSubview:a];
}

我的MapTile看起来像这样 -

-(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;
}

我的问题是,如果我在地图上移动一段时间,只有这是唯一被调用的方法,并且在只有十几个移动后它会大大减慢。

我原本每次移动时都会加载maptile图像并认为这可能是问题,所以如你所见,已经改变它,只加载图片一次并重新使用它们。我尝试使用“Beginning Iphone game development”一书中的imagecache,并在每个drawmap方法的开头清空缓存。我尝试使用自动释放池并使用autorelease标签加载tile。我尝试在绘制瓷砖时取消分配瓷砖,但正如您所料,这会破坏屏幕上的图像,因此地图不可见。

我并不懒惰,并且已经尝试过广泛地让它停止放慢速度,但不幸的是,此时它超出了我的编码技能。

非常感谢任何帮助。

提前致谢。

亚当

1 个答案:

答案 0 :(得分:5)

有很多问题:

  1. 每次绘制地图时,alloc都有MapTile个实例,但您永远不会发布它们。

  2. 每次绘制地图时,您alloc CharacterTile个实例,而您永远不会发布它。

  3. 您的MapTile构造函数会分配一个永不释放的NSString实例。

  4. 您的MapTile构造函数在retain上调用了loadedImage[pictureNumber],但没有匹配的release

  5. 您反复向视图添加MapTileCharacterTile个实例,但您的代码不会从视图中删除以前的实例。

  6. 所以1-4是不好的,但我敢打赌,#5正在扼杀你的表现。每次更新地图时,您都会累积越来越多的子视图,并且永远不会从视图中删除旧的图块。你的代码在旧版本上堆积了新的图块,并且堆越大,你的应用程序运行得越慢。

    无论如何,这应该解决问题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;
    }
    

    问题4-5你必须自己解决。但是,如果您只是更新drawMap以便在添加任何新视图之前删除所有子视图,我认为您将大部分都在那里。