Objective c 在ARC中启动新的Cocos2d iPhone项目后获取内存警告。初学者
为了学习Cocos2d,我最近一直在自学objective-c 开始了一个新的项目,用一款经典的下落宝石俄罗斯方块游戏自学基础知识。我采取的第一步是使用edit>refactor为ARC启用项目,并选择模板中的最后4个文件 到目前为止,我们已经能够通过子类化CCSprite来添加一个带有动态着色的sprite的宝石,并将其沿XCoordinates移动,同时使其从顶部掉落。gems被赋予一个gemPos位置——例如5,3——以便我以后实现匹配方法 我得到一个EXC_BAD_访问警告,当几个区块在测试项目一段时间后堆叠在一起。如果启用ARC,我不明白为什么会发生这种情况 我笨拙的代码如下(遗漏了.h文件): 默认helloworld层: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_访问警告,当几个区块在
-(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的回复-我重新启动了项目,遇到了类似的问题,因此使用了不同的解决方案来解决问题…但我认为这可能就是问题所在!