我正在使用 cocos2d 开发一款适用于 iPad 的游戏,该游戏涉及一个装有不同类型瓷砖的棋盘。我创建了一个名为 Tile
的自定义类作为图 block 的通用模板,并创建了一些 Tile
的子类,它们具有不同的属性和方法。我还创建了一个名为 Board
的类,除其他外,它使用特殊坐标系跟踪所有图 block 的位置。
出于某种原因,在 Board
类中,编译器似乎没有将 Tile
识别为一种对象,即使我已经添加了 #import "Tile.h"
在文件的顶部。
相关代码如下(请问是否还有你想看的代码的其他部分):
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
此代码甚至无法构建,我在指定位置收到以下错误:
Expected '(' before 'Tile'
如果我将类型从 (Tile*)
更改为 (NSObject*)
,它会修复错误,这让我相信 Tile
未被识别为一种对象。
我已经通过 Google 和这个网站进行了搜索,但无法弄清楚为什么会这样。
更新
愚蠢的错误;易于修复。
正如你们都指出的那样,问题是两个头文件正在相互导入,这是不允许的。目前,我已通过将 #import "Board.h"语句移动到 Tile.m 来解决问题,因为头文件中不需要它。稍后,如果我决定在 Tile.h 文件中使用 Board,我将使用前向引用 (@class Board;),正如你们中的一些人所建议的。
再次感谢!
最佳答案
这是 headers 导入 headers 的经典问题。你在这里有一个圆圈:Tile.h 正在导入 Board.h,Board.h 导入 Tile.h。这会使编译器感到困惑——它会陷入循环。
您可以通过不将 header 导入 header 来解决此问题。但是,您仍然需要让编译器了解 Tile
。在 Board.h 中,制作一个 "forward declaration"类的:
#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.
这向编译器保证有一个名为 Tile
的类将在运行时存在;然后您可以在标题的其余部分引用该名称。在 Board
的实现中,您导入了 Tile.h。这将使编译器在需要时看到与 Tile
类关联的方法和属性。
同样,将 #import "Board.h"
移动到 Tile.m 中。由于您没有引用 Tile.h 中的 Board
类,因此您不需要进行前向声明。
一般来说,最好只将类头导入到需要它们的实现文件中。框架 header ,因为它们永远不会导致您的代码出现循环,所以可以并且——因为您需要引用其中声明的许多类——应该导入到您的 header 中。
关于Objective-C 头文件无法将自定义对象识别为类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7896440/