Is this a circular reference?
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.
精彩评论