Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C header file not recognizing custom object as a type

Tags:

I'm working on a game for iPad using cocos2d which involves a board filled with different types of tiles. I've created a custom class called Tile as a general template for tiles and a few subclasses of Tile which have different properties and methods. I've also created a class called Board which, among other things, keeps track of the locations of all the tiles using a special coordinate system.

For some reason, in the Board class, the compiler doesn't seem to be recognizing Tile as a type of object, even though I've added #import "Tile.h" at the top of the file.

Here's the relevant code (just ask if there's other parts of the code you want to see):

Tile.h

#import <Foundation/Foundation.h> #import "cocos2d.h" #import "Board.h"  @interface Tile : NSObject  -(void) updateNeighbors;  @property (nonatomic, retain) CCSprite* sprite; @property (assign) CGPoint coords; @property (assign) CGPoint positionInPoints; @property (nonatomic, retain) NSMutableArray *neighbors;  @end 

Board.h

#import <Foundation/Foundation.h> #import "cocos2d.h" #import "Tile.h"  @interface Board : NSObject  +(Board*)sharedBoard;  - (void) putTile: (Tile*) tile AtIndex: (CGPoint) index; //<-- error here! - (void) replaceTileAtIndex: (CGPoint) index1 WithTileAtIndex: (CGPoint) index2; - (Tile*) tileAtIndex: (CGPoint) index; //<-- error here! - (void) populate;  @property (nonatomic, retain) NSMutableArray *tiles; @property (nonatomic, retain) NSString *type; @property (assign) CGPoint size;  @end 

This code will not even build and I'm getting the following error where indicated:

Expected '(' before 'Tile'

If I change the type from (Tile*) to (NSObject*), it fixes the error, which leads me to believe that Tile is not being recognized as a type of object.

I've searched via Google and this site and cannot figure out why this is happening.


Update

Dumb mistake; easy to fix.

As you all have pointed out the problem is that the two header files are importing each other, which is not allowed. For now, I've fixed the problem by moving the #import "Board.h" statement to Tile.m, since it isn't needed in the header file. Later on, if I decide to use Board in the Tile.h file I will use forward referencing (@class Board;), as a few of you suggested.

Thanks again!

like image 462
stephenalexbrowne Avatar asked Oct 25 '11 22:10

stephenalexbrowne


1 Answers

This is a classic problem with headers importing headers. You have a circle here: Tile.h is importing Board.h, which imports Tile.h. This confuses the compiler -- it gets stuck in a loop.

You solve this by not importing headers into headers. You still need to let the compiler know about Tile, however. In Board.h, make a "forward declaration" of the class:

#import <Foundation/Foundation.h> #import "cocos2d.h"  @class Tile;    // Dear compiler,                  // Tile is a class that I will need to refer                  // to in this file. Please consider it to be a                  // type; I promise it'll be defined at runtime.                  // Sincerely, stephenalexbrowne  @interface Board : NSObject //etc. 

This assures the compiler that there is a class called Tile that will exist at runtime; you can then refer to that name in the remainder of your header. In your implementation for Board, you import Tile.h. That will let the compiler see the methods and properties associated with the Tile class where they are needed.

Likewise, move the #import "Board.h" into Tile.m. Since you aren't referring to the Board class in Tile.h, you don't need to make a forward declaration.

In general, it is best to import your class headers only into the implementation files where they are needed. Framework headers, since they will never cause a cycle with your code, can and -- because you need to refer to many of the classes declared in them -- should be imported into your headers.

like image 80
jscs Avatar answered Sep 18 '22 14:09

jscs