Objective c 在ARC中启动新的Cocos2d iPhone项目后获取内存警告。初学者

Objective c 在ARC中启动新的Cocos2d iPhone项目后获取内存警告。初学者,objective-c,cocos2d-iphone,automatic-ref-counting,Objective C,Cocos2d Iphone,Automatic Ref Counting,为了学习Cocos2d,我最近一直在自学objective-c 开始了一个新的项目,用一款经典的下落宝石俄罗斯方块游戏自学基础知识。我采取的第一步是使用edit>refactor为ARC启用项目,并选择模板中的最后4个文件 到目前为止,我们已经能够通过子类化CCSprite来添加一个带有动态着色的sprite的宝石,并将其沿XCoordinates移动,同时使其从顶部掉落。gems被赋予一个gemPos位置——例如5,3——以便我以后实现匹配方法 我得到一个EXC_BAD_访问警告,当几个区块在

为了学习Cocos2d,我最近一直在自学objective-c

开始了一个新的项目,用一款经典的下落宝石俄罗斯方块游戏自学基础知识。我采取的第一步是使用edit>refactor为ARC启用项目,并选择模板中的最后4个文件

到目前为止,我们已经能够通过子类化CCSprite来添加一个带有动态着色的sprite的宝石,并将其沿XCoordinates移动,同时使其从顶部掉落。gems被赋予一个gemPos位置——例如5,3——以便我以后实现匹配方法

我得到一个EXC_BAD_访问警告,当几个区块在测试项目一段时间后堆叠在一起。如果启用ARC,我不明白为什么会发生这种情况

我笨拙的代码如下(遗漏了.h文件):

默认helloworld层:

-(id) init
    {

        if( (self=[super init]) ) {

            oldGems = [[NSMutableArray alloc]init];

            [self setIsTouchEnabled:YES];

            [self newGem];

            [self scheduleUpdate];

        }
        return self;
    }

    - (void)registerWithTouchDispatcher
    {
        [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
    }

    - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
    {
        CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
        oldPos = touchLocation;
        return TRUE;
    }

    - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
    {
        CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
        [self updateXCoord:(CGPoint)touchLocation];
    }

    - (void)updateXCoord:(CGPoint)touchLocation
    {


        CGPoint distance = ccpSub(touchLocation, oldPos);
        float xDistance = distance.x;

        if (abs(xDistance) >= 36) {
            if (touchLocation.x > oldPos.x) {
                [_thisGem setPosition:ccp([_thisGem position].x + 36, [_thisGem position].y)];
                [_thisGem setGemPos:ccp([_thisGem gemPos].x+1,[_thisGem gemPos].y)];
                NSLog(@"The gem position is %@", NSStringFromCGPoint([_thisGem gemPos]));
                oldPos = touchLocation;
            } else {
                [_thisGem setPosition:ccp([_thisGem position].x - 36, [_thisGem position].y)];
                [_thisGem setGemPos:ccp([_thisGem gemPos].x-1,[_thisGem gemPos].y)];
                NSLog(@"The gem position is %@", NSStringFromCGPoint([_thisGem gemPos]));
                oldPos = touchLocation;
            }
        }


    }

    - (void)newGem
    {
        if (_thisGem) {
            PCGem *oldGem = _thisGem;
            NSLog(@"Old gem position at %@", NSStringFromCGPoint([oldGem gemPos]));
            [oldGems addObject:oldGem];
        }

        _thisGem = [[PCGem alloc] initWithGemColor];
        [_thisGem setPosition:ccp(160, 450)];
        [self addChild:_thisGem];
        [_thisGem setGemPos:ccp(4,10)];

        NSLog(@"Gem added with %@ color", [_thisGem gemColorName]);
    }

    - (void)update:(ccTime)dt
    {

        if ([_thisGem gemPos].y > 0)  {

            [self spaceBelowOccupied];

            [_thisGem setPosition:ccp([_thisGem position].x, [_thisGem position].y-1)];
            [_thisGem setGemPos:ccp([_thisGem gemPos].x, floor([_thisGem position].y / 36))];

        } else {
            [self newGem];
        }
    }

    - (void)spaceBelowOccupied
    {    
            for (PCGem *occupiedTile in oldGems) {
                if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
                    NSLog(@"Collision detected!");
                    [self newGem];
                }
            }
    }
    - (id)initWithGemColor
    {
        if ((self = [super initWithFile:@"gemGS.png"])) {


            NSArray *gemColorList = [NSArray arrayWithObjects:(NSString *)@"blue", (NSString *)@"red", (NSString *)@"green", nil];

            NSInteger randColor = arc4random_uniform(3);

            switch (randColor) {
                case 0:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:0]];

                    ccColor3B gemColorRGB = {0,0,255};
                    [self setColor:gemColorRGB];
                    break;
                }
                case 1:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:1]];

                    ccColor3B gemColorRGB = {255,0,0};
                    [self setColor:gemColorRGB];            
                    break;
                }
                case 2:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:2]];

                    ccColor3B gemColorRGB = {0,255,0};
                    [self setColor:gemColorRGB];
                    break;
                }
            }

        }

        return self;

    }
和我笨拙的PCGem类:

-(id) init
    {

        if( (self=[super init]) ) {

            oldGems = [[NSMutableArray alloc]init];

            [self setIsTouchEnabled:YES];

            [self newGem];

            [self scheduleUpdate];

        }
        return self;
    }

    - (void)registerWithTouchDispatcher
    {
        [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
    }

    - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
    {
        CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
        oldPos = touchLocation;
        return TRUE;
    }

    - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
    {
        CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
        [self updateXCoord:(CGPoint)touchLocation];
    }

    - (void)updateXCoord:(CGPoint)touchLocation
    {


        CGPoint distance = ccpSub(touchLocation, oldPos);
        float xDistance = distance.x;

        if (abs(xDistance) >= 36) {
            if (touchLocation.x > oldPos.x) {
                [_thisGem setPosition:ccp([_thisGem position].x + 36, [_thisGem position].y)];
                [_thisGem setGemPos:ccp([_thisGem gemPos].x+1,[_thisGem gemPos].y)];
                NSLog(@"The gem position is %@", NSStringFromCGPoint([_thisGem gemPos]));
                oldPos = touchLocation;
            } else {
                [_thisGem setPosition:ccp([_thisGem position].x - 36, [_thisGem position].y)];
                [_thisGem setGemPos:ccp([_thisGem gemPos].x-1,[_thisGem gemPos].y)];
                NSLog(@"The gem position is %@", NSStringFromCGPoint([_thisGem gemPos]));
                oldPos = touchLocation;
            }
        }


    }

    - (void)newGem
    {
        if (_thisGem) {
            PCGem *oldGem = _thisGem;
            NSLog(@"Old gem position at %@", NSStringFromCGPoint([oldGem gemPos]));
            [oldGems addObject:oldGem];
        }

        _thisGem = [[PCGem alloc] initWithGemColor];
        [_thisGem setPosition:ccp(160, 450)];
        [self addChild:_thisGem];
        [_thisGem setGemPos:ccp(4,10)];

        NSLog(@"Gem added with %@ color", [_thisGem gemColorName]);
    }

    - (void)update:(ccTime)dt
    {

        if ([_thisGem gemPos].y > 0)  {

            [self spaceBelowOccupied];

            [_thisGem setPosition:ccp([_thisGem position].x, [_thisGem position].y-1)];
            [_thisGem setGemPos:ccp([_thisGem gemPos].x, floor([_thisGem position].y / 36))];

        } else {
            [self newGem];
        }
    }

    - (void)spaceBelowOccupied
    {    
            for (PCGem *occupiedTile in oldGems) {
                if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
                    NSLog(@"Collision detected!");
                    [self newGem];
                }
            }
    }
    - (id)initWithGemColor
    {
        if ((self = [super initWithFile:@"gemGS.png"])) {


            NSArray *gemColorList = [NSArray arrayWithObjects:(NSString *)@"blue", (NSString *)@"red", (NSString *)@"green", nil];

            NSInteger randColor = arc4random_uniform(3);

            switch (randColor) {
                case 0:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:0]];

                    ccColor3B gemColorRGB = {0,0,255};
                    [self setColor:gemColorRGB];
                    break;
                }
                case 1:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:1]];

                    ccColor3B gemColorRGB = {255,0,0};
                    [self setColor:gemColorRGB];            
                    break;
                }
                case 2:
                {
                    [self setGemColorName:[gemColorList objectAtIndex:2]];

                    ccColor3B gemColorRGB = {0,255,0};
                    [self setColor:gemColorRGB];
                    break;
                }
            }

        }

        return self;

    }
这就引出了另一个问题,我似乎找不到答案。在启用ARC的Cocos2d项目示例中,我看到了使用的节点便利方法,当然是alloc]init]autorelease]。但我想你不能使用自动释放和ARC,这会导致崩溃?这是怎么回事

对我的不幸有什么想法吗?请澄清:)

干杯


Adrian

我认为这可能是由于在数组中枚举时编辑数组造成的。在更新函数中,您可以调用SpaceBelowOccuped:

- (void)spaceBelowOccupied
{    
        for (PCGem *occupiedTile in oldGems) {
            if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
                NSLog(@"Collision detected!");
                [self newGem];
            }
        }
}
然后,如果在for循环中调用了newGem,并且该循环成功:

if (_thisGem) {
        PCGem *oldGem = _thisGem;
        NSLog(@"Old gem position at %@", NSStringFromCGPoint([oldGem gemPos]));
        [oldGems addObject:oldGem];
    }
然后,在枚举数组时将对象添加到数组中。因此,请将您的SpaceBelowOccuped更改为此,并查看它是否有效:

 - (void)spaceBelowOccupied
{    
        for (PCGem *occupiedTile in [oldGems copy]) {
            if (CGRectIntersectsRect(occupiedTile.boundingBox, _thisGem.boundingBox)) {
                NSLog(@"Collision detected!");
                [self newGem];
            }
        }
}

通过这种方式,您可以复制一份oldGems进行枚举,一旦完成,它将自动删除。

哪一行实际崩溃?当我单击EXC_BAD_ACCESS notifier时,它会将我带到main.m(这表示哪些行崩溃?抱歉,新建),并指向:int retVal=UIApplicationMain(argc,argv,nil,@“AppController”);它位于@autoreleasepool中。虽然这让我感到困惑,因为我认为启用ARC并不需要这样做?此外,通过使用NSLogs,我发现在我的-(void)末尾收到“gem added with%@color”消息时添加了一个新的gemnewGem方法,所以我认为这与更新方法有关?也许我试图以每秒60帧的速度一次做太多事情(快速枚举所有未使用的gem,以检测与当前下降的gem的碰撞-可以更有效地处理prob)?感谢Marcus的回复-我重新启动了项目,遇到了类似的问题,因此使用了不同的解决方案来解决问题…但我认为这可能就是问题所在!