使用这些代码时有什么区别:
#import <UIKit/UIKit.h>
#import "Foo.h"
@interface EditFooViewController : UIViewController {
Foo *foo;
}
@end
和
#import <UIKit/UIKit.h>
@class Foo;
@interface EditFooViewController : UIViewController {
Foo *foo;
}
@end
答案 0 :(得分:2)
我相信你寻求的答案是here。
答案 1 :(得分:2)
前者导入头文件Foo.h
,根据惯例,可能(但不一定)声明一个名为Foo
的类。
后者声明你的代码中的其他地方,你将定义一个名为Foo
的类,所以可以像Foo *foo;
这样做,你可以信任我这个类{ {1}}存在。
你倾向于使用Foo
,你有循环类依赖;即,类@class Foo
声明类型为Foo
的实例变量,而类Bar
声明类型为Bar
的实例变量。
答案 2 :(得分:1)
第二个变体forward声明了Foo,这意味着编译器将知道存在一个类Foo,但没有更多关于它的信息。即不是它的大小或成员。对于这里的用法,这是不需要的。
第二种变体有时可能优于第一种变体,因为它限制了依赖性。即,EditFooViewController的用户不需要依赖Foo.h。
答案 3 :(得分:1)
@class Foo;
是“前瞻性声明”。考虑编译器实际看到的内容很有用:编译器总是一次编译一个.m文件。在EditFooViewController.m文件中,您可能从:
#import "EditFooViewController.h"
#import "Foo.h"
那么在那时,编译器实际看到的是:
...the contents of UIKit.h
@class Foo;
@interface EditFooViewController : UIViewController {
Foo *foo;
@end
...the contents of Foo.h, i.e.
@interface Foo
...
@end
...the contents of your .m file.
正如您所看到的,您可以声明引用Foo类的EditFooViewController的接口,但是当EditFooViewController.m导入Foo.h时,它实际上定义在它下面。
实际上,只要你的类引用了ivars或方法声明中的其他类,你就应该使用前向声明(即@class Foo;
)。
例外情况是,如果您的类是子类或实现协议,您需要实际#import
定义协议或超类的头文件。这是因为当第三个类导入子类的头文件时,它需要超类/原型的声明,并且您不希望必须导入所有超类/原型的头文件。这也解释了为什么你需要头文件顶部的#import <UIKit/UIKit.h>
(而不是简单地将超类声明为@class UIViewController;
)。