在我的游戏模型中需要有关内存管理问题的帮助

时间:2010-04-05 06:01:35

标签: iphone memory-management

我是初学级程序员,试图为iphone制作游戏应用程序,到目前为止,我遇到了程序内存管理(exc_bad_access)可能存在的问题。我搜索并阅读了几篇关于内存管理的文章(包括苹果的文档),但我仍然无法弄清楚我的代码到底出了什么问题。所以如果有人可以帮我清理我为自己制造的烂摊子,我真的很感激。

//in the .h file
@property(nonatomic,retain) NSMutableArray *fencePoleArray;
@property(nonatomic,retain) NSMutableArray *fencePoleImageArray;
@property(nonatomic,retain) NSMutableArray *fenceImageArray;

//in the .m file
- (void)viewDidLoad {
    [super viewDidLoad];
    self.gameState = gameStatePaused;

    fencePoleArray = [[NSMutableArray alloc] init];
    fencePoleImageArray = [[NSMutableArray alloc] init];
    fenceImageArray = [[NSMutableArray alloc] init];

    mainField = CGRectMake(10, 35, 310, 340);

    ..........

    [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(gameLoop) userInfo:nil repeats:YES];
}

所以基本上,玩家触摸屏幕来设置围栏/杆

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(.......) {

    .......

    }
    else {
        UITouch *touch = [[event allTouches] anyObject];
        currentTapLoc = [touch locationInView:touch.view];

        NSLog(@"%i, %i", (int)currentTapLoc.x, (int)currentTapLoc.y);

        if(CGRectContainsPoint(mainField, currentTapLoc)) {
            if([self checkFence]) {
                onFencePole++;
                //this 3 set functions adds their respective objects into the 3 NSMutableArrays using addObject:
                [self setFencePole];
                [self setFenceImage];
                [self setFencePoleImage];

                .......

                }
            }
            else {
                .......
            }
        }
    }
}

setFence函数(setFenceImage和setFencePoleImage与此类似)

-(void)setFencePole {
    Fence *fencePole;
    if (!elecFence) {
        fencePole = [[Fence alloc] initFence:onFencePole fenceType:1 fencePos:currentTapLoc];
    }
    else {
        fencePole = [[Fence alloc] initFence:onFencePole fenceType:2 fencePos:currentTapLoc];
    }
    [fencePoleArray addObject:fencePole];
    [fencePole release];

每当我按下游戏中的按钮时,会调用endOpenState来清除屏幕上的所有额外图像(栅栏/柱子),并删除3 NSMutableArray中的所有现有对象。要点是删除NSMutableArrays中的所有对象,但保留数组本身,以便以后可以重用。

-(void)endOpenState {

    ........

    int xMax = [fencePoleArray count];
    int yMax = [fenceImageArray count];

    for (int x = 0; x < xMax; x++) {
        [[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
    }

    for (int y = 0; y < yMax; y++) {
        [[fenceImageArray objectAtIndex:y] removeFromSuperview];
    }

    [fencePoleArray removeAllObjects];
    [fencePoleImageArray removeAllObjects];
    [fenceImageArray removeAllObjects];

    ........
}

崩溃发生在checkFence函数。

-(BOOL)checkFence {
    if (onFencePole == 0) {
        return YES;
    }
    else if (onFencePole >= 1 && onFencePole < currentMaxFencePole - 1) {
        CGPoint tempPoint1 = currentTapLoc;
        CGPoint tempPoint2 = [[fencePoleArray objectAtIndex:onFencePole-1] returnPos]; // the crash happens at this line
        if ([self checkDistance:tempPoint1 point2:tempPoint2]) {
            return YES;
        }
        else {
            return NO;
        }
    }
    else if (onFencePole == currentMaxFencePole - 1) {

    ......

    }
    else {
        return NO;
    }
}

所以这里的问题是,一切正常,直到调用endOpenState后第二次调用checkFence。所以就像tap_screen - &gt; tap_screen - &gt; press_button_to_call_endOpenState - &gt;点击屏幕 - &gt; tap_screen - &gt;碰撞

我正在考虑的是当我使用[fencePoleArray removeAllObjects]时,fencePoleArray搞砸了,因为当我发表评论时它并没有崩溃。如果有人能向我解释出了什么问题,真的会很棒。并提前感谢。

2 个答案:

答案 0 :(得分:0)

如果您想使用属性,则应使用self.propertyName = ...代替propertyName = ...

希望这会有所帮助。

答案 1 :(得分:0)

首先,提出几点建议:

if (!elecFence) {
    fencePole = [[Fence alloc] initFence:onFencePole
        fenceType:1 fencePos:currentTapLoc];
}
else {
    fencePole = [[Fence alloc] initFence:onFencePole
        fenceType:2 fencePos:currentTapLoc];
}

你这太难了,怎么样:

const int fenceType = elecFence ? 2 : 1;
Fence *fencePole = [[Fence alloc] initFence:onFencePole
        fenceType:fenceType fencePos:currentTapLoc];

而且:

int xMax = [fencePoleArray count];
int yMax = [fenceImageArray count];

for (int x = 0; x < xMax; x++) {
    [[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
}

for (int y = 0; y < yMax; y++) {
    [[fenceImageArray objectAtIndex:y] removeFromSuperview];
}

可以使用makeObjectsPerformSelector:

进行缩短
const SEL remove = @selector(removeFromSuperview);
[fencePoleImageArray makeObjectsPerformSelector:remove];
[fenceImageArray makeObjectsPerformSelector:remove];

这更短更安全,因为代码中的xMax绑定是从fencePoleArray计算的,用于迭代fencePoleImageArray。 (可能是对的,可能是错的。)

现在转到objectAtIndex:电话。如果数组仍在内存中并且您尝试访问数组边界之外的对象,则会出现异常。所以我猜这个数组或其中的一些对象是在你不知道的情况下发布的。您可以尝试NSLog数组和给定索引上的对象,并尝试记录它们的retainCount。如果日志记录行崩溃,您已找到已释放的对象并可以开始查找原因。

(还有一件事:您应该将游戏逻辑拆分为一个单独的模型类。这样可以简化代码并使其更易于推理。)