开发者

Is this a circular reference?

开发者 https://www.devze.com 2023-04-04 12:28 出处:网络
I have a class that inherits from CCSprite called GameObject.I also have a singleton called ActionDispatcher that inherits from NSObject.

I have a class that inherits from CCSprite called GameObject. I also have a singleton called ActionDispatcher that inherits from NSObject.

The ActionDispatcher sharedActionDispatcher's job is to return a CCActionInterval when asked, and the method that does this requires a reference to the asking object, which is of type GameObject (or a subclass thereof). But for the GameObject to be able to ask for this, it needs to refer to ActionDispatcher. So I have a #import "GameObject.h" in the ActionDispatcher header and a #import "ActionDispatcher" in the GameObject header.

I get an error: Expected ')' before 'GameObject' in the ActionManager method that takes a reference to a GameObject.

EDIT: added comments to show where I fixed this per the accepted answer below.


//The GameObject interface

#import "cocos2d.h"
#import "ActionDispatcher.h"

@interface GameObject : CCSprite {
    CGPoint homeLocation;
}

@property (readwrite) CGPoint homeLocation;

- (void)updateStateWithDeltaTime:(ccTime)deltaTime 
        andListOfGameObjects:(CCArray*)listOfGameObjects;

@end

//The GameObject implementation

#import "GameObject.h"

@implementation GameObject

@synthesize homeLocation;

- (void)updateStateWithDeltaTime:(ccTime)deltaTime 
        andListOfGameObjects:(CCArray *)listOfGameObjects 
{
    //CCLOG(@"updateStateWithDeltaTime method should be overriden");
}

@end

//The ActionDispatcher interface

#import "cocos2d.h"
#import "CCRotateAround.h"
#import "Constants.h"
#import "GameObject.h" // Answer: Remove this line

// Add this here: @class GameObject;

@interface ActionDispatcher : NSObject {

}

+ (ActionDispatcher *)sharedActionDispatcher;

- (id)actionWithType:(ActionType)actionType 
          withObject:(GameObject *)gameObject 
        withDuration:(float)duration;

@end

//The ActionDispatcher implementation

开发者_StackOverflow中文版#import "ActionDispatcher.h"
// and add this here: #import "GameObject.h"

@implementation ActionDispatcher

static ActionDispatcher* _sharedActionDispatcher = nil;

+ (ActionDispatcher*)sharedActionDispatcher 
{
    @synchronized([ActionDispatcher class])                             
    {
        if(!_sharedActionDispatcher)                                    
            [[self alloc] init]; 
        return _sharedActionDispatcher;                                 
    }
    return nil; 
}

+ (id)alloc 
{
    @synchronized ([ActionDispatcher class])                            
    {
        NSAssert(_sharedActionDispatcher == nil,
                 @"Attempted to allocated a second instance of the ActionManager singleton");                                          
        _sharedActionDispatcher = [super alloc];
        return _sharedActionDispatcher;                                 
    }
    return nil;  
}

- (id)actionWithType:(ActionType)actionType 
          withObject:(GameObject *)gameObject 
        withDuration:(float)duration
{
    CGSize screenSize = [[CCDirector sharedDirector] winSize];

    id action = nil;

    switch (actionType) {
        case kActionDiveBomb:
            CCLOG(@"ActionManager returning action of type: dive bomb");
            CGPoint controlPoint1 = ccp(gameObject.position.x, gameObject.position.y*0.5f);
            CGPoint controlPoint2 = ccp(screenSize.width*0.5f, gameObject.position.y*0.5f);
            CGPoint destination = ccp(screenSize.width*0.5f, -gameObject.contentSize.height*0.5f);
            ccBezierConfig diveBombBezier;
            diveBombBezier.controlPoint_1 = controlPoint1;
            diveBombBezier.controlPoint_2 = controlPoint2;
            diveBombBezier.endPosition = destination;
            id diveAction = [CCBezierTo actionWithDuration:duration bezier:diveBombBezier];
            id returnToTopAction = [CCMoveTo actionWithDuration:0.0f position:ccp(gameObject.homeLocation.x, screenSize.height+gameObject.contentSize.height/2)];
            id fallInAction = [CCMoveTo actionWithDuration:duration*0.2 position:gameObject.homeLocation];
            action = [CCSequence actions:diveAction, returnToTopAction, fallInAction, nil];
            break;
        case kActionLoop:
            CCLOG(@"ActionManager returning action of type: loop");
            CGPoint centerPoint = ccp(screenSize.width/2, screenSize.height/2);
            float span = 360.0;
            action = [CCRotateAround actionWithDuration:duration centerPoint:centerPoint spanAngle:span];
            break;
        case kActionSpin:
            CCLOG(@"ActionManager returning action of type: spin");
            action = [CCRotateBy actionWithDuration:duration angle:360.0f];
            break;
        case kActionGoHome:
            CCLOG(@"ActionManager returning action of type: go home");
            action = [CCMoveTo actionWithDuration:0.0f position:[gameObject homeLocation]];
            break;
        case kActionFallIn:
            CCLOG(@"ActionManager returning action of type: fall in");
            action = [CCMoveTo actionWithDuration:duration position:[gameObject homeLocation]];
            break;
        case kActionIdle:
            CCLOG(@"ActionManager returning action of type: idle");
            action = [CCDelayTime actionWithDuration:duration];
            break;
        default:
            CCLOG(@"ActionManager returning action of type: no valid action");
            break;
    }

    return action;
}

@end


Just add a @class directive in ActionDispatcher.h above the @interface. This is a forward declaration of a class that is imported in the implementation.

@class GameObject;


Possible. Try inserting

@class GameObject

forward declaration after the import in ActionManager.m? This should break the cycle.


This is not the problem. #import directive automatically handles inclusion of already included files. Discussion is here. To check it comment out all other imports, subclass your GameObject from NSObject and it will compile without errors. The error tells you there is something wrong in one of the files you include. Sometimes it can be a wrong symbol in a header file after the @end keyword, which makes the compiler complain in the wrong place.

0

精彩评论

暂无评论...
验证码 换一张
取 消