一尘不染

Swift中是否有Prefix Header(或带有此功能的东西)?

swift

有没有办法在Swift中获得前缀标头的功能?我不想在使用它们的每个文件中导入外部库。


阅读 576

收藏
2020-07-07

共1个答案

一尘不染

不。但是您不需要它-无需花费太多import UIKit时间即可输入十二个字符。(或使用已经在其中的Xcode New File模板。)

那就是TLDR。对于整个故事,请继续阅读…


在(Obj)C中,使API在源代码文件中可用的旧方法是 文本包含 。预处理程序将看到您的#import <Foundation/Foundation.h>指令,并在将其传递给编译器之前, 将所有文件
从该头文件(及其包含的任何其他头文件,以及它们包含的头文件,等等) 复制 到源文件中。如您所料, 为项目中的每个文件
重新编译数千行系统标头声明并不是那么有效。

因此,几年前我们就获得了预编译的头文件-
您将commons放在#import了一个地方,这些部分的编译步骤将执行一次,结果是编译器后端可以为项目中的每个文件重用。但这也有问题:保持PCH满意会带来维护负担,并且它不允许您限制每个源文件中使用的名称空间(即,如果您希望.m项目中的一个文件仅查看其需要的符号,使用,而不是项目中其他地方使用的所有其他东西)。

最重要的是,文本包含具有潜在的脆弱性问题。如果行#define上方的#import内容定义更改了导入的标题中使用的符号,则这些标题将发生编译错误(或以更细微的方式失败,例如定义错误的API)。有一些惯例可以阻止这种情况的发生,但是没有强制执行惯例-
您总是错别字/新团队成员/糟糕的合并,而不会崩溃。

无论如何,即使使用预编译的标题,文本包含也不是很好,因此Apple在Xcode 5中引入了 Modules
。(实际上,不仅是Apple。它们在LLVM /
Clang编译器套件中,因此它们是开源的。
)模块基于 语义导入
,而不是文本包含-也就是说,模块在抽象级别告诉编译器什么它提供给您的源代码的API符号,而不是粘贴这些符号定义的文本-
因此它们不易碎,并且在后端分别进行了预编译,因此可以快速进行项目构建。

现在,模块是ObjC项目的默认模块。(请注意,如果您创建一个新的ObjC项目,它不再包含预编译的头文件。您可以关闭模​​块,因此,如果您有一个旧项目,则可能仍在使用文本包含和预编译的头文件。)您可以找到WWDC
2013的Session
404中
有关于ObjC模块的更多信息。


为什么所有关于ObjC的事情?我们在谈论Swift,对吗?好吧,Swift基于许多相同的基础架构。

Swift从一开始就使用模块,因此它始终基于语义导入。这意味着没有构建时性能的损失,也没有脆弱性。Swift
import所做的只是告诉编译器您需要哪些符号(以及链接程序在生成二进制可执行文件时在哪里可以找到它们)。

因此,将相同的imports放在每个文件顶部的唯一开销就是打字。这是必要的成本—在Swift中,源文件是一个语义单元,决定其中包含的内容是真正的含义。例如,如果您import Foundation启用了Cocoa集合和值类型的桥接,那么许多Swift标准库类型的行为都会发生变化,如果您的应用程序中有一部分想要严格使用Swift集合和值类型,那么您可能不希望导入Foundation(或Cocoa或UIKit或其他包含它的东西)。


更新: 此外,您import在Swift文件中选择的内容具有实际意义。

例如,编译器如何优化泛型和静态/动态分配取决于给定文件中可见的声明,因此,如果import您需要的内容过多,则可能会生成较慢的代码。因此,通常,最好import仅满足您的需求。

显式导入还有助于提高清晰度和可读性。如果imports在整个项目范围内,那么当您将代码从一个项目复制粘贴到另一个项目中时,您会在新位置看到很多错误…而import要解决的问题就变得不那么清楚了。他们。


你说:“但是我讨厌一直把相同的数放在import每个文件的开头。” 让我们考虑一下。

  • 您真的需要 几个 吗?大多数模块会传递import其依赖关系。import Foundation如果您已经在使用importCocoa(OS X)或UIKit(iOS / tvOS / watchOS),则不需要。例如,如果您正在编写SpriteKit或SceneKit游戏,则可以免费自动获得UIKit / Cocoa(适用于任何平台)和Foundation。

  • 您真的需要 每个文件都一样 吗?当然,您在UIKit项目中,因此几乎在所有地方都使用UIKit。但这只是import顶部的十二个字符。也许您的项目也使用了Contacts或Photos或CoreBluetooth或HealthKit …,但是它可能不需要使用您定义的每种类型的所有对象。(如果这样做,您的代码可能会遭受关注点分离不良的困扰。)

  • 您是否真的 一直在 管理import报表?我对您的项目一无所知,但在我从事的大多数大型项目中,我至少要说90%的开发活动都涉及编辑现有的源文件,而不是创建新的文件…主要功能是,很少(重新)定义源文件集或它们的依赖项。还有一些快捷方式可以帮助(尤其是)设置导入,例如Xcode文件模板。 __

2020-07-07