Objective c 为什么在AppDelegate.h中为ViewController使用@class而不是#import?

Objective c 为什么在AppDelegate.h中为ViewController使用@class而不是#import?,objective-c,uiviewcontroller,Objective C,Uiviewcontroller,我在目标C中有一个基本的最佳实践问题。我理解@class和#import之间的区别,但我不理解默认的Apple Xcode模板为什么会这样做: AppDelegate.h: @class视图控制器 .m: #导入“ViewController.h 当您可以将后一个#import放在.h中,并将ViewController放在.m中,从而简化了一行代码 当然,保存一行代码不是问题,我只是好奇为什么会这样做?行@class ViewController;是一个转发声明,因此编译器知道名称ViewCo

我在目标C中有一个基本的最佳实践问题。我理解
@class
#import
之间的区别,但我不理解默认的Apple Xcode模板为什么会这样做:

AppDelegate.h:

@class视图控制器

.m:

#导入“ViewController.h

当您可以将后一个
#import
放在
.h
中,并将
ViewController
放在
.m
中,从而简化了一行代码


当然,保存一行代码不是问题,我只是好奇为什么会这样做?

@class ViewController;
是一个转发声明,因此编译器知道名称
ViewController
应该是什么意思。重点是尽量在头文件中执行少量的
#导入
,以避免出现错误加快速度

想象一个文件
a.h
,它导入了“b.h”“
。现在,导入
a.h
的每个文件都会自动导入
b.h
,这增加了编译器必须完成的工作量。通过使用前向声明,通常可以避免此类额外的导入,从而避免编译器的额外工作

项目越大,类层次结构和依赖关系越复杂,这些导入问题就越严重。因此,在可能的情况下养成使用前向声明的习惯是一个好主意

编辑:在注释之后,另一个重要的用例浮出水面:解决循环依赖关系。例如,如果类A希望引用类B,反之亦然,则必须先定义一个类,然后再定义另一个类。但因为他们需要了解对方,我们就有了一个悖论。问题是这样解决的:

// Tell the compiler: B will be a class type.
@class B;

// Now we can define A, the compiler has enough
// information to know what B means.
@interface A : NSObject {
    B *b;
}
@end

// Since A is now defined, we can define B.
// Cycle is resolved.
@interface B : NSObject {
    A *a;
}
@end

转发类声明:

@class ClassName;
在不需要特定属性、属性或方法信息的头文件中使用

这允许头文件的
#import
#include
,而无需使用
#import
ing ClassName.h带来的任何开销。

#import
用于我们或Apple xcode预定义的类,但在定义它之前我们使用@class(它是类的前向声明),在我们的家长/或上一节课上


因此,它会告诉编译器在我们的项目中有一个具有此名称的类,这样编译器就不会为该类名设置错误。

除了编译时间之外,实际程序性能是否会受到这两种方法的影响?darkdustAs dreamlax说,非常简单的解释,运行时不受此影响。这仅在编译时有效,因此编译器大致了解名称(类型)应该是什么。在要使用该类实例的
.m
文件中,您需要执行
#import
操作,编译器将了解所有细节,如方法名和其他符号。是的,但是
RootViewController.h
看起来像什么?Xcode只将
.m
文件一次传递给编译器。一个
.m
文件然后导入它需要的所有
.h
文件。这就是为什么您可以设置
.m
文件的目标成员身份,但不能设置
.h
文件的目标成员身份。编译器不会将
.m
.h
文件成对处理,它不知道(也不关心)两者之间的任何关系。事实上,您可以随意命名
.h
文件,扩展名
.h
只是一种惯例。格式可以显著改进。