我的询问是这个。什么时候使用#import和何时使用@class?
简单的答案:您#import
或#include
有身体依赖性时。否则,您使用前向声明(@class MONClass
,struct MONStruct
,@protocol MONProtocol
)。
以下是一些常见的身体依赖性示例:
- 任何C或C ++值(指针或引用不是物理依赖性)。如果您具有
CGPoint
ivar或属性,则编译器将需要查看的声明CGPoint
。
- 你的超人。
- 您使用的方法。
有时,如果我使用@class声明,则会看到常见的编译器警告,例如以下内容:“警告:接收者'FooController'是正向类,并且相应的@interface可能不存在。
编译器在这方面实际上非常宽容。它将删除提示(例如上面的提示),但是如果您忽略它们并且操作不#import
正确,则可以轻松地破坏堆栈。尽管应该(IMO),但编译器不会强制执行此操作。在ARC中,编译器更加严格,因为它负责引用计数。发生的情况是,当编译器遇到您调用的未知方法时,它会使用默认值。假定每个返回值和参数均为id
。因此,您应该消除代码库中的所有警告,因为这应被视为物理依赖性。这类似于调用未声明的C函数。对于C,假定参数为int
。
您偏爱前向声明的原因是因为可以将依赖关系降到最低,因此可以通过一些因素减少构建时间。使用前向声明,编译器可以看到一个名称,并且可以在没有物理依赖项的情况下正确解析和编译程序,而无需查看类声明或其所有依赖项。干净的构建花费更少的时间。增量构建花费的时间更少。当然,您最终将花费更多的时间来确保每个翻译都可以看到所需的所有标头,但这可以迅速减少构建时间(不算小项目)。
如果使用#import
或#include
代替,那么您在编译器上投入的工作比必要的要多得多。您还将引入复杂的标头依赖项。您可以将其比作蛮力算法。当您使用时#import
,您将拖入大量不必要的信息,这需要大量内存,磁盘I / O和CPU来解析和编译源。
在依赖方面,ObjC非常接近于基于C的语言的理想选择,因为NSObject
类型从不值- NSObject
类型始终是引用计数的指针。因此,如果适当地构建程序的依赖项并尽可能进行转发,则可以避免令人难以置信的快速编译时间,因为几乎不需要物理依赖项。您还可以在类扩展中声明属性,以进一步降低依赖性。对于大型系统而言,这是一个巨大的好处-如果您曾经开发过大型C ++代码库,您就会知道它的不同之处。
因此,我的建议是在可能的情况下使用转发,然后#import
在存在物理依赖性的地方使用转发。如果看到警告或其他暗示着身体依赖的警告,请全部解决。该修复程序#import
位于您的实现文件中。
在构建库时,您可能会将某些接口归为一组,在这种情况下,您会将#import
引入物理依赖关系的库(例如#import <AppKit/AppKit.h>
)。这可能会引入依赖关系,但是库维护人员通常可以根据需要为您处理物理依赖关系-如果他们引入了功能,则可以最大程度地减少对构建的影响。