@import vs #import - iOS 7

时间:2013-09-22 18:47:45

标签: ios objective-c import ios7

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

@import UIKit;

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

6 个答案:

答案 0 :(得分:825)

这是一项名为模块或“语义导入”的新功能。会话WWDC 2013205404视频中有更多信息。这是预编译头文件的一种更好的实现。 您可以将模块与iOS 7和Mavericks中的任何系统框架一起使用。模块是框架可执行文件及其标题的打包,并被吹捧为比#import更安全,更高效

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

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

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

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

enter image description here

Xcode 5中的新项目默认启用模块。要在较旧的项目中启用它们,请进入项目构建设置,搜索“模块”并将“启用模块”设置为“是”。 “Link Frameworks”也应该是“YES”:

您必须使用Xcode 5和iOS 7或Mavericks SDK,但您仍然可以发布较旧的操作系统(例如iOS 4.3或其他)。 模块不会更改代码的构建方式或任何源代码。


来自WWDC幻灯片:

  
      
  • 导入框架的完整语义描述
  •   
  • 不需要解析标题
  •   
  • 导入框架界面的更好方法
  •   
  • 加载二进制表示
  •   
  • 比预编译标题更灵活
  •   
  • 免疫当地宏观定义的影响(例如#define readonly 0x01
  •   
  • 默认情况下为新项目启用
  •   

明确使用模块:

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

您还可以使用此表示法导入一个标题:

@import iAd.ADBannerView;

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

答案 1 :(得分:44)

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

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

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

#import <SomeLibrary/SomeFile.h>

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

@import SomeLibrary;

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

@import AwesomeLibrary.AwesomeObject;

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

看来,自从使用CLANG_ENABLE_MODULES

启用clang模块后,XCode 7.x会出现很多警告

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

历史:

#include => #import => .pch => @import

#include vs #import
.pch - Precompiled header

模块-@import

Product Name == Product Module Name 

@module声明要求编译器加载预编译框架的二进制文件,该二进制文件减少了构建时间。模块化框架包含.modulemap [About]

如果在Xcode项目中启用了模块功能#include,并且#import伪指令将自动转换为@import,从而带来所有优势

enter image description here