根据我的理解,在ClassA需要包含ClassB标头,而ClassB需要包含ClassA标头以避免任何循环包含的情况下,应该使用前向类声明。我还理解#import是一个简单的ifndef,因此include只发生一次。

我的问题是:什么时候使用#import,什么时候使用@class?有时如果我使用@class声明,我看到一个常见的编译器警告,如下所示:

警告:接收端FooController是转发类,对应的@interface可能不存在。

我真的很想理解这一点,而不是仅仅删除@class forward-declaration并抛出一个#import来沉默编译器给我的警告。


当前回答

当我发展的时候,我脑中只有三件事,这三件事从来不会给我带来任何问题。

导入超类 导入父类(当您有子类和父类时) 在项目外部导入类(比如在框架和库中)

对于所有其他类(我的项目中的子类和子类),我通过forward-class声明它们。

其他回答

可以把@class看作是告诉编译器“相信我,这是存在的”。

可以把#import看作是复制-粘贴。

出于多种原因,您希望最小化导入的数量。在没有任何研究的情况下,首先想到的是它减少了编译时间。

注意,当从类继承时,不能简单地使用前向声明。您需要导入文件,以便您声明的类知道它是如何定义的。

常见的做法是在头文件中使用@class(但仍然需要#import父类),在实现文件中使用#import。这样可以避免任何圆形夹杂物,而且效果很好。

另一个优点:快速编译

如果包含头文件,其中的任何更改都会导致当前文件也被编译,但如果类名被包含为@class name,则不会出现这种情况。当然,您需要在源文件中包含头文件

如果我们这么做

@interface Class_B : Class_A

意味着我们将Class_A继承到Class_B,在Class_B中我们可以访问Class_A的所有变量。

如果我们这样做

#import ....
@class Class_A
@interface Class_B

这里我们说我们在程序中使用Class_A,但如果我们想在Class_B中使用Class_A变量,我们必须在.m文件中#import Class_A(创建一个对象并使用它的函数和变量)。

如果你试图在头文件中声明一个变量,或者一个属性,你还没有导入,你会得到一个错误,说编译器不知道这个类。

你的第一个想法可能是导入它。 在某些情况下,这可能会导致问题。

例如,如果你在头文件中实现了一堆c方法,或者结构,或者类似的东西,因为它们不应该被多次导入。

因此你可以用@class告诉编译器:

我知道你不知道那门课,但它确实存在。它将被导入或在其他地方实现

它基本上告诉编译器关闭并编译,即使它不确定这个类是否会被实现。

通常在.m文件中使用#import,在.h文件中使用@class。