我试图编译,但每次我做,一个方法抛出一个奇怪的“预期一个类型”的错误。我有一个方法在标题:
-(ANObject *)generateSomethingForSomethingElse:(NSString *)somethingElse;
此方法的返回类型的错误点。我已经导入ANObject到头使用#import“ANObject.h”和ANObject正在编译精细..
为什么会发生这种情况?
解决方法
这是与编译源文件的顺序有关。你可能已经知道你不能在定义之前调用一个方法(见下面的伪代码):
var value = someMethod(); function someMethod() { ... }
这将导致编译时错误,因为someMethod()尚未定义。类同样如此。类由编译器依次编译。
所以,如果你想象所有的类在编译前放入一个巨大的文件,你可能已经可以看到这个问题。让我们看看Ship和BoatYard类:
@interface BoatYard : NSObject @property (nonatomic,retain) Ship* currentShip; @end @interface Ship : NSObject @property (nonatomic,retain) NSString* name; @property (nonatomic,assign) float weight; @end
再次,因为Ship类尚未定义,我们不能引用它。解决这个特殊的问题很简单;更改编译顺序并编译。我相信你是这个屏幕在XCode的家庭:
但是你知道你可以在列表中上下拖动文件吗?这改变了文件将被编译的顺序。因此,只需移动Ship类上面的Ship类,一切都很好。
但是,如果你不想这样做,或者更重要的是,如果两个对象之间存在循环关系怎么办?让我们通过添加对当前ShipYard的引用来增加该对象图的复杂性:
@interface BoatYard : NSObject @property (nonatomic,retain) BoatYard* currentBoatYard; @property (nonatomic,assign) float weight; @end
哦,亲爱的,现在我们有一个问题。这两个不能并行编译。我们需要一种方法来通知编译器Ship *类确实存在。这就是为什么@class关键字是如此方便。
用俗人的话来说,你是说:“相信我,船真的存在,你会很快看到它。把它放在一起:
@class Ship; @interface BoatYard : NSObject @property (nonatomic,assign) float weight; @end
现在编译器知道它编译BoatYard,一个Ship类定义很快就会出现。当然,如果没有,编译仍然会成功。
所有的@class关键字确实告诉编译器该类很快就会出现。它不是#import的替代品。您仍然必须导入头文件,否则您将无法访问任何类的内部:
@class Ship -(void) example { Ship* newShip = [[Ship alloc] init]; }
这不能工作,并将失败,并显示一条错误消息,说明Ship是转发声明。一旦你#import“Ship.h”,那么你将能够创建对象的实例。