当前位置: 首页 > 面试题库 >

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

柳修为
2023-03-14
问题内容

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


问题答案:

不。但是您不需要它-无需花费太多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文件模板。 __



 类似资料:
  • Java有Future或FutureTask,可以在新线程中运行任务。然后,将执行结果返回到原始线程。Swift中是否有任何功能可以实现这一点?

  • 问题内容: 如何检查jQuery中元素的存在? 我当前的代码是这样的: 有没有更优雅的方式来解决这个问题?也许是插件还是功能? 问题答案: 在JavaScript中,一切都是“真实的”或“虚假的”,对于数字(和NaN)而言,一切都是其他。所以你可以这样写: 您不需要那部分。

  • 问题内容: 在Swift中,转义的闭包参数用注释。在Objective- C中是否有任何等效项,以便将生成的Swift接口标记为? 问题答案: 是的,但是从您在问题中提出的建议来看是落后的。规则是,除非明确标记,否则Objective-C不可为空的块会 自动 转换为Swift作为函数。 __

  • 问题内容: SASS具有一个称为的功能,该功能允许选择器继承另一个选择器的属性,但不复制属性(如mixins)。 LESS是否也具有此功能? 问题答案: 是的,Less.js推出的V1.4.0。 LESS没有实现SASS和Stylus使用的at- rule()语法,而是实现了伪类语法,这为LESS的实现提供了灵活性,使其可以直接应用于选择器本身或在语句内部。因此,这两个都将起作用: 要么 此外,您

  • 问题内容: 目前,我正在开发中使用mysql 5.7,在生产中使用5.6。每次我在开发中使用group by运行查询时,都会收到类似“错误代码:1055。SELECT列表的表达式#1不在GROUP BY中”的错误。 这是查询。 为了解决这个问题,我使用5.7 ANY_VALUE中的mysql函数,但是主要问题是它在mysql 5.6中不可用 因此,如果我修复开发的sql语句,我将在生产中出现错误。

  • 问题内容: 在某些javascript实现(Rhino,SpiderMonkey)中没有 noSuchMethod 功能。 我想知道,是否有一种方法可以对物业进行类似的处理?我想编写可以在属性和方法上分派的代理类。 问题答案: 更新: ECMAScript6代理现在已得到广泛支持。基本上,如果您不需要支持IE11,则可以使用它们。 代理对象使您可以定义基本操作的自定义行为,例如属性查找,赋值,枚举