首页 文章

@import vs #import - iOS 7

提问于
浏览
413

我正在玩一些新的iOS 7功能,并使用WWDC视频_197603中讨论的一些图像效果 . 为了在会话的源代码中产生模糊效果, UIImage 通过导入UIKit的类别进行了扩展,如下所示:

@import UIKit;

我想我在另一个会话视频中看到了一些关于此的内容,但我找不到它 . 我正在寻找有关何时使用此功能的任何背景信息 . 它只能用于Apple框架吗?使用此编译器指令的好处是否应该返回并更新旧代码?

5 回答

  • 3

    它目前仅适用于内置系统框架 . 如果你像苹果一样使用 #import 仍然在app委托中导入 UIKit 框架它被替换(如果模块已打开且被识别为系统框架),编译器会将其重新映射为模块导入而不是导入头文件无论如何 . 因此,保留 #import 与其转换为模块导入的方式完全相同

  • 41

    您可以在Objective-C学习可可的书中找到很好的答案(ISBN:978-1-491-90139-7)

    模块是一种将文件和库包含并链接到项目中的新方法 . 要了解模块如何工作以及它们有什么好处,重要的是回顾一下Objective-C和#import语句的历史 . 每当您想要包含一个文件以供使用时,通常会有一些代码如下所示:

    #import "someFile.h"
    

    或者在框架的情况下:

    #import <SomeLibrary/SomeFile.h>
    

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

    使用 #import 时,您无需担心此问题或编写 Headers 保护以避免此问题 . 但是, #import 仍然只是一个美化的复制粘贴操作,导致许多其他较小但仍然非常危险的问题(例如,包含的文件覆盖您在自己的代码中已在其他地方声明的内容)的编译时间较慢 .

    模块试图解决这个问题 . 它们不再是复制并粘贴到源代码中,而是包含的文件的序列化表示,只有在需要时才可以将其导入到源代码中 . 通过使用模块,代码通常编译得更快,并且比使用#include或 #import 更安全 .

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

    #import <SomeLibrary/SomeFile.h>
    

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

    @import SomeLibrary;
    

    这还有Xcode将SomeLibrary框架自动链接到项目中的额外好处 . 模块还允许您仅将实际需要的组件包含在项目中 . 例如,如果要在AwesomeLibrary框架中使用AwesomeObject组件,通常必须导入所有内容才能使用单件 . 但是,使用模块,您只需导入要使用的特定对象:

    @import AwesomeLibrary.AwesomeObject;
    

    对于在Xcode 5中制作的所有新项目,默认情况下启用模块 . 如果您想在旧项目中使用模块(并且您确实应该),则必须在项目的构建设置中启用它们 . 一旦这样做,您可以在代码中同时使用 #import@import 语句,而无需担心 .

  • 1

    看来,自从使用 CLANG_ENABLE_MODULES 启用clang模块后,XCode 7.x会出现很多警告

    看看Lots of warnings when building with Xcode 7 with 3rd party libraries

  • 812

    这是一个名为 Modules 或"semantic import"的新功能 . 会话205404WWDC 2013视频中有更多信息 . 这是预编译头文件的更好实现 . You can use modules with any of the system frameworks in iOS 7 and Mavericks. 模块是框架可执行文件及其 Headers 的打包,被吹捧为比 #import 更安全,更高效 .

    使用 @import 的一大优势是 you don't need to add the framework in the project settings, it's done automatically . 这意味着您可以跳过单击加号按钮并搜索框架(黄金工具箱)的步骤,然后将其移至"Frameworks"组 . 它将从隐秘的"Linker error"消息中拯救许多开发人员 .

    You don't actually need to use the @import keyword. 如果您选择使用模块,则所有 #import#include 指令都会映射为自动使用 @import . 这意味着你没有好好使用PCH,或者你的项目有很多小的源文件 .

    模块是为大多数Apple框架(UIKit,MapKit,GameKit等)预先构建的 . 您可以将它们与您自己创建的框架一起使用:如果您创建了一个框架,它们将自动创建Xcode中的Swift框架,你可以自己为any Apple or 3rd-party library手动创建一个".modulemap"文件 .

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

    enter image description here

    Modules are enabled by default in new projects in Xcode 5 . 要在较旧的项目中启用它们,请转到项目构建设置,搜索"Modules"并将"Enable Modules"设置为"YES" . "Link Frameworks"也应该是"YES":

    您必须使用Xcode 5和iOS 7或Mavericks SDK,但您仍然可以发布较旧的操作系统(比如iOS 4.3或其他) . Modules don't change how your code is built or any of the source code.


    来自WWDC幻灯片:

    导入框架的完整语义描述不需要解析标头更好的方式导入框架的接口加载二进制表示比预编译标头更灵活免受本地宏定义的影响(例如#define readonly 0x01)通过新项目启用默认


    To explicitly use modules:

    #import <Cocoa/Cocoa.h> 替换为 @import Cocoa;

    您也可以使用此表示法导入一个 Headers :

    @import iAd.ADBannerView;
    

    子模块在Xcode中自动完成 .

  • 2

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

相关问题