关于C#:@import vs #import – iOS 7

@import vs #import - iOS 7

我正在使用一些新的iOS 7功能,并使用WWDC视频"在iOS上实现吸引人的用户界面"中讨论的一些图像效果。为了在会话的源代码中产生模糊效果,UIImage通过导入uikit的类别进行了扩展,如下所示:

1
@import UIKit;

我想我在另一个视频中看到了一些关于这个的东西,但是我找不到它。我在找什么时候用这个的背景资料。它只能用于Apple框架吗?使用这个编译器指令的好处是否足以让我返回并更新旧代码?


这是一个称为模块或"语义导入"的新功能。WWDC 2013视频中有205和404部分的更多信息。它是预编译头的一种更好的实现。您可以将模块与iOS 7和Mavericks中的任何系统框架一起使用。模块是框架可执行文件和它的头文件的打包,被吹捧为比#import更安全、更高效。

使用@import的一个主要优点是不需要在项目设置中添加框架,它是自动完成的。这意味着您可以跳过单击加号按钮并搜索框架(黄金工具箱)的步骤,然后将其移动到"框架"组。它将从神秘的"链接器错误"消息中节省许多开发人员。

您实际上不需要使用@import关键字。如果您选择使用模块,那么所有#import#include指令都会自动映射为使用@import。这意味着您不必更改源代码(或从其他地方下载的库的源代码)。假设使用模块也可以提高构建性能,特别是如果您没有很好地使用PCH或者您的项目有许多小的源文件。

模块是为大多数苹果框架(uikit、mapkit、gamekit等)预先构建的。您可以将它们与您自己创建的框架一起使用:如果您在Xcode中创建一个Swift框架,它们将自动创建,并且您可以为任何Apple或第三方库手动创建一个".modulemap"文件。

您可以使用代码完成来查看可用框架的列表:

enter image description here

在Xcode5的新项目中,模块默认启用。要在旧项目中启用它们,请进入项目生成设置,搜索"模块",并将"启用模块"设置为"是"。"链接框架"也应为"是":

您必须使用Xcode5和iOS7或MavericksSDK,但是您仍然可以为旧的OSS发布(比如iOS4.3或其他)。模块不会改变代码的构建方式或任何源代码。

从WWDC幻灯片:

  • Imports complete semantic description of a framework
  • Doesn't need to parse the headers
  • Better way to import a framework’s interface
  • Loads binary representation
  • More flexible than precompiled headers
  • Immune to effects of local macro definitions (e.g. #define readonly 0x01)
  • Enabled for new projects by default

要显式使用模块:

@import Cocoa;替换#import

您也可以只导入一个带有此符号的标题:

1
@import iAd.ADBannerView;

子模块在Xcode中为您自动完成。


你可以在《客观C学习可可》一书中找到一个很好的答案(ISBN:978-1-491-90139-7)

模块是将文件和库包含并链接到项目中的一种新方法。为了了解模块的工作原理和它们有什么好处,回顾一下Objective-C和导入声明的历史是很重要的。每当您想要包含一个文件以供使用时,通常都会有一些代码如下所示:

1
#import"someFile.h"

或者对于框架:

1
#import <SomeLibrary/SomeFile.h>

因为objective-c是C编程语言的超集,所以import状态是对C的#include语句的一个小改进。include语句非常简单;它在编译期间将所包含文件中找到的所有内容复制到代码中。这有时会导致严重的问题。例如,假设您有两个头文件:SomeFileA.hSomeFileB.hSomeFileA.h包括SomeFileB.hSomeFileB.h包括SomeFileA.h。这会创建一个循环,并会混淆coimpiler。为了解决这个问题,C程序员必须编写防止此类事件发生的保护措施。

当使用#import时,您不需要担心这个问题,也不需要编写头部保护来避免它。但是,#import仍然只是一个美化的复制和粘贴操作,导致编译时间在其他一些较小但仍然非常危险的问题(例如,覆盖您在自己的代码中声明的内容的包含文件)中变慢。

模块就是试图绕过这个问题。它们不再是复制粘贴到源代码中,而是包含的文件的序列化表示,这些文件只能在需要时和需要时导入到源代码中。通过使用模块,代码通常编译更快,并且比使用include或#import更安全。

返回上一个导入框架的示例:

1
#import <SomeLibrary/SomeFile.h>

要将此库作为模块导入,代码将更改为:

1
@import SomeLibrary;

这增加了Xcode自动将somelibrary框架链接到项目中的额外功能。模块还允许您只将真正需要的组件包含到项目中。例如,如果您想要在awsomelibrary框架中使用awsomeobject组件,那么通常您必须导入所有内容才能使用一个工件。但是,使用模块,您可以只导入要使用的特定对象:

1
@import AwesomeLibrary.AwesomeObject;

对于在Xcode5中创建的所有新项目,默认情况下都启用模块。如果要在较旧的项目中使用模块(并且确实应该这样做),则必须在项目的生成设置中启用这些模块。一旦这样做了,您就可以在代码中同时使用#import@import语句,而不必担心。


它目前只适用于内置系统框架。如果你像苹果一样使用#import,仍然在应用程序委托中导入UIKit框架,那么它会被替换(如果模块已打开,并且它被识别为系统框架),编译器会将其重新映射为模块导入,而不是头文件的导入。因此,如果可能的话,离开#import将与转换为模块导入一样。


由于Xcode 7.x在使用CLANG_ENABLE_MODULES启用clang模块时,似乎会发出很多警告。

使用Xcode7和第三方库构建时,请查看大量警告


使用模块有一些好处。除非创建了模块映射,否则只能将其与苹果的框架一起使用。@import与添加到.pch文件时预编译头文件有点相似,这是一种调整应用程序编译过程的方法。此外,您不必以旧的方式添加库,使用@import实际上更快、更高效。如果你仍然在寻找一个很好的参考,我强烈建议你阅读这篇文章。