简体   繁体   English

Objective-C头文件无法将自定义对象识别为类型

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

I'm working on a game for iPad using cocos2d which involves a board filled with different types of tiles. 我正在使用cocos2d开发一款适用于iPad的游戏,其中包含一块充满不同类型瓷砖的电路板。 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. 我已经创建了一个名为Tile的自定义类作为Tile的一般模板和一些具有不同属性和方法的Tile子类。 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. 我还创建了一个名为Board的类,除其他外,它使用特殊的坐标系跟踪所有图块的位置。

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. 出于某种原因,在Board类中,编译器似乎没有将Tile识别为一种对象,即使我在文件顶部添加了#import "Tile.h"

Here's the relevant code (just ask if there's other parts of the code you want to see): 这是相关的代码(只是询问是否有你想看的代码的其他部分):

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 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' 预期'('在'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. 如果我将类型从(Tile*)更改为(NSObject*) ,它会修复错误,这使我相信Tile不会被识别为一种对象。

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. 现在,我通过将#import“Board.h”语句移动到Tile.m来解决问题,因为头文件中不需要它。 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. 稍后,如果我决定在Tile.h文件中使用Board,我将使用前向引用(@class Board;),正如你们中的一些建议的那样。

Thanks again! 再次感谢!

This is a classic problem with headers importing headers. 这是标头导入标头的典型问题。 You have a circle here: Tile.h is importing Board.h, which imports Tile.h. 你有一个圆圈:Tile.h导入Board.h,导入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. 但是,您仍然需要让编译器了解Tile In Board.h, make a "forward declaration" of the class: 在Board.h中,进行类的“前向声明”

#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; 这可以确保编译器在运行时存在一个名为Tile的类; you can then refer to that name in the remainder of your header. 然后,您可以在标题的其余部分中引用该名称。 In your implementation for Board , you import Tile.h. 在您的Board实现中,您导入Tile.h. That will let the compiler see the methods and properties associated with the Tile class where they are needed. 这将让编译器在需要它们的地方查看与Tile类相关的方法和属性。

Likewise, move the #import "Board.h" into Tile.m. 同样,将#import "Board.h"移动到Tile.m. Since you aren't referring to the Board class in Tile.h, you don't need to make a forward declaration. 由于您没有在Tile.h中引用Board类,因此您无需进行前向声明。

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. 框架标题,因为它们永远不会导致代码循环,可以 - 并且 - 因为您需要引用其中声明的许多类 - 应该导入到标题中。

Two files cannot import each other. 两个文件无法互相导入。 You need to move the import directives to the implementation files, and instead just forward-declare the classes in the headers (eg @class Tile; in Board.h). 您需要将导入指令移动到实现文件,而只是在标头中转发声明类(例如@class Tile;在Board.h中)。

The reason circular imports don't work is because #import literally includes the text from the imported file in-place. 循环导入不起作用的原因是因为#import字面上包含来自导入文件的文本。 But it also ensures that the text from a file will only be included once, in order to avoid duplicate declarations. 但它也确保文件中的文本只包含一次,以避免重复声明。 So when Tile.h says that the text from Board.h needs to go before it, and Board.h says the text from Tile.h needs to go before it, there's literally nothing the compiler can do — one of them needs to go first, and that file is going to complain because it was expecting the other one to already be there. 因此,当Tile.h说Board.h中的文本需要在它之前时,并且Board.h说Tile.h中的文本需要在它之前进行,所以编译器几乎没有什么可以做的 - 其中一个需要去首先,该文件将抱怨,因为它期待另一个已经存在。

This may not be the problem, but what happens if you remove the "#import "Board.h"" from the Tile.h file. 这可能不是问题,但是如果从Tile.h文件中删除“#import”Board.h“”会发生什么。 You might have a problem with circular referencing 您可能遇到循环引用问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM