在sprite.runAction之后调用Block时崩溃

时间:2012-05-19 07:36:16

标签: objective-c ios cocos2d-iphone objective-c-blocks

我遇到了Objective C的问题。 我在移动精灵之后试图调用一个块

我想要实现的短版本是我想要移动阵列中的所有敌人,当每个人完成移动时我想检查它是否已经碰撞。

下面的简化代码显示了我正在尝试做的事情。

我的Actor类定义如下

// -----------------------------
// Actor.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "ScreenObject.h"

typedef void (^actorMoveComplete)(void);

@interface Actor : ScreenObject
{
   // actorMoveComplete onMoveComplete;
}

@property (nonatomic) BOOL isMoving;
@property (readwrite, copy) actorMoveComplete onMoveComplete;
@property (nonatomic, retain) CCSprite* sprite;

-(void) moveTo:(CGPoint)targetPosition Speed:(float) speed withCallback:(actorMoveComplete)moveComplete;

@end

// -----------------------------
//  Actor.m
#import "Actor.h"

@implementation Actor

@synthesize onMoveComplete;
@synthesize sprite;

-(void) moveTo:(CGPoint)targetPosition Speed:(float) speed withCallback:(actorMoveComplete)moveComplete;
{
    onMoveComplete = moveComplete;

    id actionMove = [CCMoveTo actionWithDuration:speed position:targetPosition];
    id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)];
    [super.sprite runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}

-(void) spriteMoveFinished:(id) sender
{
    isMoving = NO;
    if (onMoveComplete != nil)
        onMoveComplete();
}
@end

正如您所看到的,我正在尝试将块存储在 onMoveComplete 参数中(我也在私有变量中尝试过),然后在精灵移动完成后调用它。

在我的通话类中,我正在遍历一群演员(敌人),我想在移动完成后为每个演员调用这个匿名代码块:

{
   [self checkForCollision:enemy];
}

我的通话类看起来像这样。

//------------------------------
//
//  GameLayer.h

#import "cocos2d.h"
#import "Actor.h"

@interface GameLayer : CCLayerColor
{
}

@property (nonatomic, copy) NSMutableArray *enemies;

- (void) updateEnemies;
- (void) checkForCollision:(Actor*)actor;
- (BOOL) isMapGridClear:(CGPoint)mapGrid excludeActor:(Actor*)actor;

@end


//------------------------------
//  GameLayer.m

#import "GameLayer.h"


@implementation GameLayer

@synthesize enemies;

- (void) updateEnemies
{

    for (Actor *enemy in enemies)
    {
        //  
        CGPoint newPosition = [self getNewPosition:enemy]; /* method to figure out new position */

        [enemy moveDelta:ccp(dX, dY) Speed:enemySpeed withCallback:^{
            [self checkForCollision:enemy];
        }];
    }
}


- (void) checkForCollision:(Actor*)actor
{
    if (![self isMapGridClear:actor.gridPosition excludeActor:actor])
    {
        actor.isCrashed=YES;
        [actor loadSprite:self spriteImage:@"crashed.png"];
    }
}


- (BOOL) isMapGridClear:(CGPoint)mapGrid excludeActor:(Actor*)actor
{
    /* Actual method figures out if there was a collision    */
    return YES;
}

@end

不幸的是,当我调用onMoveComplete块时,我不断收到EXC_BAD_ACCESS错误 有趣的是,如果我尝试在moveTo方法中调用块,它可以工作(但当然我想在移动完成后触发它)。

任何人都可以帮助我解决我的错误。我甚至使用正确的机制?

(格式不正确,代码段不完整的道歉)

1 个答案:

答案 0 :(得分:2)

您正确地将属性声明为副本,但是您将实例变量直接设置为块的地址,而不使用生成的访问器。这意味着该块在被调用之前不会被复制并被销毁。

使用self.onMoveCompleted = moveCompleted分配你的阻止,你会没事的。