我正在玩一些新的iOS 7功能,并使用WWDC视频“在iOS上实现Engaging UI”中讨论的一些Image Effects。为了在会话的源代码中产生模糊效果,UIImage
通过导入UIKit的类别进行了扩展,如下所示:
@import UIKit;
我想我在另一个会话视频中看到了有关此内容的信息,但是我很难找到它。我正在寻找有关何时使用它的任何背景信息。只能与Apple框架一起使用吗?使用此编译器指令的好处是否足以使我返回并更新旧代码?
我正在玩一些新的iOS 7功能,并使用WWDC视频“在iOS上实现Engaging UI”中讨论的一些Image Effects。为了在会话的源代码中产生模糊效果,UIImage
通过导入UIKit的类别进行了扩展,如下所示:
@import UIKit;
我想我在另一个会话视频中看到了有关此内容的信息,但是我很难找到它。我正在寻找有关何时使用它的任何背景信息。只能与Apple框架一起使用吗?使用此编译器指令的好处是否足以使我返回并更新旧代码?
Answers:
这是一个称为模块或“语义导入” 的新功能。WWDC 2013视频中有关于Session 205和404的更多信息。这是对预编译标头的更好实现。您可以将模块与iOS 7和Mavericks中的任何系统框架一起使用。模块是框架可执行文件及其标头的封装,并且被吹捧为比更加安全,高效#import
。
使用的最大优点之一@import
是,您无需在项目设置中添加框架,而是自动完成的。这意味着您可以跳过单击加号按钮并搜索框架(黄金工具箱)的步骤,然后将其移至“框架”组。它将使许多开发人员免受神秘的“链接器错误”消息的影响。
您实际上不需要使用@import
关键字。如果您选择使用模块,则all #import
和#include
指令都将映射为@import
自动使用。这意味着您不必更改源代码(或从其他位置下载的库的源代码)。据说使用模块也可以提高构建性能,尤其是在您没有很好地使用PCH或项目中有许多小源文件的情况下。
模块是为大多数Apple框架(UIKit,MapKit,GameKit等)预先构建的。您可以将它们与自己创建的框架一起使用:如果您在Xcode中创建Swift框架,则会自动创建它们,并且您可以自己为任何Apple或3rd-party库手动创建“ .modulemap”文件。
您可以使用代码完成来查看可用框架的列表:
默认情况下,在Xcode 5的新项目中启用了模块。要在较旧的项目中启用它们,请进入项目构建设置,搜索“模块”,然后将“启用模块”设置为“是”。“链接框架”也应为“是”:
您必须使用Xcode 5和iOS 7或Mavericks SDK,但仍可以发布用于较旧的操作系统(例如iOS 4.3或其他版本)。模块不会改变代码或任何源代码的构建方式。
从WWDC幻灯片中:
- 导入框架的完整语义描述
- 不需要解析头
- 导入框架接口的更好方法
- 加载二进制表示
- 比预编译头更灵活
- 不受本地宏定义的影响(例如
#define readonly 0x01
)- 默认情况下为新项目启用
要显式使用模块:
替换#import <Cocoa/Cocoa.h>
为@import Cocoa;
您也可以仅使用以下符号导入一个标头:
@import iAd.ADBannerView;
子模块会在Xcode中为您自动完成。
@import sqlite3
对我来说似乎有用,因为我为它创建了自己的module.map,当我意识到sqlite包含在OS X中并删除了我的module.map时,编译器继续使用旧模块。
您可以在《用Objective-C学习可可》(ISBN:978-1-491-90139-7)一书中找到不错的答案
模块是一种将文件和库包含并链接到项目中的新方法。要了解模块如何工作以及它们有什么好处,回顾一下Objective-C和#import语句的历史很重要,只要想包含一个文件供使用,通常就会有一些类似以下的代码:
#import "someFile.h"
或就框架而言:
#import <SomeLibrary/SomeFile.h>
因为Objective-C是C编程语言的超集,所以#import #include
声明是对C 语句的较小改进。#include语句非常简单;它将在编译过程中将在包含的文件中找到的所有内容复制到您的代码中。有时这可能会导致严重的问题。例如,假设您有两个头文件:SomeFileA.h
和SomeFileB.h
; SomeFileA.h
包括SomeFileB.h
,并且SomeFileB.h
包括SomeFileA.h
。这将创建一个循环,并可能使coimpiler混淆。为了解决这个问题,C程序员必须编写防范此类事件发生的措施。
使用时#import
,您无需担心此问题,也不必编写标题保护程序来避免此问题。但是,#import
这仍然只是美化的复制和粘贴操作,从而在许多其他较小但仍然非常危险的问题之间引起了缓慢的编译时间(例如,包含的文件将覆盖您在自己的代码中其他地方声明的内容)。
模块是一种尝试来解决这个问题。它们不再是对源代码的复制粘贴,而是对包含文件的序列化表示,仅当需要它们时,才可以将其导入源代码。通过使用模块,代码通常比使用#include或#include更快,并且更安全#import
。
回到前面的导入框架示例:
#import <SomeLibrary/SomeFile.h>
要将这个库作为模块导入,代码将更改为:
@import SomeLibrary;
这具有Xcode自动将SomeLibrary框架链接到项目中的额外好处。模块还允许您仅将真正需要的组件包含到项目中。例如,如果要在AwesomeLibrary框架中使用AwesomeObject组件,通常只需要导入所有内容即可使用一个。但是,使用模块,您可以仅导入要使用的特定对象:
@import AwesomeLibrary.AwesomeObject;
对于使用Xcode 5创建的所有新项目,默认情况下启用模块。如果您想在较旧的项目中使用模块(确实应该),则必须在项目的构建设置中将其启用。一旦这样做,就可以在代码中一起使用#import
和@import
语句,而无需担心。
似乎自XCode 7.x起,在启用clang模块时发出了许多警告 CLANG_ENABLE_MODULES
使用模块有一些好处。除非创建了模块映射,否则您只能在Apple的框架中使用它。@import
与添加到.pch
文件中的预编译头文件有点类似,这是调整应用程序编译过程的一种方式。另外,您不必以旧的方式添加库@import
,实际上使用起来更加快捷高效。如果您仍在寻找不错的参考,我强烈建议您阅读本文。
历史:
#include => #import => .pch => @import
模块- @import
Product Name == Product Module Name
@module
声明告诉编译器加载框架的预编译二进制文件,这样可以减少构建时间。模块化框架包含.modulemap
[关于]
如果在Xcode项目中启用了模块功能,#include
并且#import
指令自动转换为@import
带来所有优势,