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

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

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

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


当前回答

这是一个示例场景,其中我们需要@class。

考虑一下,如果您希望在头文件中创建一个协议,该协议的参数具有相同类的数据类型,那么您可以使用@class。请记住,您也可以单独声明协议,这只是一个示例。

// DroneSearchField.h

#import <UIKit/UIKit.h>
@class DroneSearchField;
@protocol DroneSearchFieldDelegate<UITextFieldDelegate>
@optional
- (void)DroneTextFieldButtonClicked:(DroneSearchField *)textField;
@end
@interface DroneSearchField : UITextField
@end

其他回答

另一个优点:快速编译

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

查看关于ADC的Objective-C编程语言文档

在定义类|类接口一节中,它描述了为什么这样做:

@class指令最大限度地减少了编译器和链接器看到的代码量,因此是给出类名正向声明的最简单方法。由于简单,它避免了导入仍然导入其他文件的文件时可能出现的潜在问题。例如,如果一个类声明了另一个类的静态类型实例变量,并且它们的两个接口文件相互导入,那么两个类都不能正确编译。

有关文件依赖关系& #import & @class的更多信息,请查看以下内容:

http://qualitycoding.org/file-dependencies/ 这是篇好文章

文章摘要

imports in header files: #import the superclass you’re inheriting, and the protocols you’re implementing. Forward-declare everything else (unless it comes from a framework with a master header). Try to eliminate all other #imports. Declare protocols in their own headers to reduce dependencies. Too many forward declarations? You have a Large Class. imports in implementation files: Eliminate cruft #imports that aren’t used. If a method delegates to another object and returns what it gets back, try to forward-declare that object instead of #importing it. If including a module forces you to include level after level of successive dependencies, you may have a set of classes that wants to become a library. Build it as a separate library with a master header, so everything can be brought in as a single prebuilt chunk. Too many #imports? You have a Large Class.

这是一个示例场景,其中我们需要@class。

考虑一下,如果您希望在头文件中创建一个协议,该协议的参数具有相同类的数据类型,那么您可以使用@class。请记住,您也可以单独声明协议,这只是一个示例。

// DroneSearchField.h

#import <UIKit/UIKit.h>
@class DroneSearchField;
@protocol DroneSearchFieldDelegate<UITextFieldDelegate>
@optional
- (void)DroneTextFieldButtonClicked:(DroneSearchField *)textField;
@end
@interface DroneSearchField : UITextField
@end

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

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

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

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

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

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

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