我正在玩弄一些新的iOS 7功能,并使用WWDC视频“在iOS上实现引人入胜的UI”中讨论的一些图像效果。为了在会话的源代码中产生模糊效果,通过导入UIKit来扩展UIImage
类别:
@import UIKit;
我记得在另一个会议视频中看到有关此事的内容,但我很难找到它。我正在寻找任何关于何时使用这个的背景信息。它只能与苹果框架一起使用吗?使用这个编译指令的好处足以让我回头更新旧代码吗?
我正在玩弄一些新的iOS 7功能,并使用WWDC视频“在iOS上实现引人入胜的UI”中讨论的一些图像效果。为了在会话的源代码中产生模糊效果,通过导入UIKit来扩展UIImage
类别:
@import UIKit;
我记得在另一个会议视频中看到有关此事的内容,但我很难找到它。我正在寻找任何关于何时使用这个的背景信息。它只能与苹果框架一起使用吗?使用这个编译指令的好处足以让我回头更新旧代码吗?
#import
更安全和高效。@import
的一个重要优点是无需在项目设置中添加框架,它会自动完成。这意味着您可以跳过点击加号搜索框架(金色工具箱)并将其移动到“框架”组的步骤。它将使许多开发人员免受神秘的“链接器错误”消息的困扰。
您实际上不需要使用@import
关键字。如果您选择使用模块,所有的#import
和#include
指令都会自动映射到使用@import
。这意味着您不必更改源代码(或从其他地方下载的库的源代码)。据说使用模块也可以提高构建性能,特别是如果您没有很好地使用PCHs或者您的项目有许多小的源文件。
大多数苹果框架(UIKit、MapKit、GameKit等)都预先构建了模块。您可以将它们用于自己创建的框架:如果您在Xcode中创建一个Swift框架,它们会自动创建,您还可以手动为任何苹果或第三方库创建“.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 时,编译器继续使用旧的模块。 - bames53你可以在《Learning Cocoa with 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.h
和SomeFileB.h
; SomeFileA.h
包含SomeFileB.h
,而SomeFileB.h
包含SomeFileA.h
。这会创建一个循环,并且可能会使编译器混淆。为了解决这个问题,C程序员必须编写防止此类事件发生的保护措施。#import
更安全。#import <SomeLibrary/SomeFile.h>
为将这个库作为一个模块导入,代码需要改为:
@import SomeLibrary;
这样做的额外好处是Xcode会自动将SomeLibrary框架链接到项目中。模块还允许您仅将您真正需要的组件包含到您的项目中。例如,如果您想在AwesomeLibrary框架中使用AwesomeObject组件,通常情况下您必须导入所有内容才能使用其中一个部分。然而,使用模块,您只需导入您想要使用的特定对象:
@import AwesomeLibrary.AwesomeObject;
Xcode 5中默认启用了模块,对于所有新项目都是如此。如果你想要在旧项目中使用模块(你确实应该这样做),则必须在项目的构建设置中启用它们。一旦这样做,您可以在代码中同时使用#import
和@import
语句而不必担心任何问题。
@import模块(ObjC)或语义导入
而不是使用通常的模块
//as example
#include <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
历史:
[#include -> #import] -> [预编译头文件 .pch] -> @import Module(ObjC); -> [导入模块(Swift)]
它是LLVM模块的一部分。
@import <module_name>;
声明告诉编译器要加载(而不是编译)一个预编译模块的二进制文件,从而减少构建时间。以前,每次运行时编译器都会编译依赖项,但现在应该事先编译并仅加载。
//previously
run into dependency -> compile dependency
run into dependency -> compile dependency
//@import
compile dependency
run into dependency -> load compiled binary
run into dependency -> load compiled binary
[模块映射] - 模块和头文件之间的桥梁
Xcode
启用模块 (C 和 Objective-C) (CLANG_ENABLE_MODULES)
- CLANG 的#include, #import
指令会自动转换为@import
,带来所有的优势。因为包含头文件和子/模块之间的映射,所以Modulemap
可以无缝地完成这项工作。
传递-fmodules
#include, #import -> @import
Link Frameworks Automatically(CLANG_MODULES_AUTOLINK)
- 启用系统模块自动链接。需要激活CLANG_ENABLE_MODULES
。自动链接允许基于#import,@import(Objective-C),import(Swift)
传递-framework <framework_name>
如果是NO- 会传递-fno-autolink
标志
CLANG_ENABLE_MODULES == NO and CLANG_MODULES_AUTOLINK == NO
如果您想要手动处理系统(#import <UIKit/UIKit.h>
)链接(而不是自动链接),您有两个选择:
将依赖项添加到General -> Frameworks and Libraries 或 Frameworks, Libraries, and Embedded Content
Build Settings -> Other Linker Flags(OTHER_LDFLAGS) -> -framework <module_name>
如果出现以下情况,将会抛出下一个错误:
Undefined symbol: _OBJC_CLASS_$_UIView
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_UIView", referenced from:
objc-class-ref in ClassB.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
CLANG_ENABLE_MODULES
已禁用CLANG_MODULES_AUTOLINK
已禁用且没有手动链接逆向工程
otool -l <binary>
//-l print the load commands
//find LC_LINKER_OPTION
//cmd LC_LINKER_OPTION
目前仅适用于内置系统框架。如果您像苹果一样在应用委托中使用#import
导入UIKit
框架,则会被替换(如果模块打开并且已识别为系统框架),编译器将重新映射它为模块导入而不是头文件的导入。
因此,保留#import
与其转换为模块导入后几乎相同。
看起来自从 XCode 7.x 版本以后,启用 CLANG_ENABLE_MODULES
模块会导致大量警告。
@import
与添加到 .pch
文件时预编译头文件有些相似,这是调整应用程序编译过程的一种方式。此外,您不必以旧的方式添加库,实际上使用 @import
更快更有效。如果您仍在寻找一个好的参考资料,我强烈推荐阅读this article。
.mm
文件或者说Objective-C++
,目前还不支持使用@import
(我已经尝试过使用g++
和clang++
进行测试,但是并没有成功)。 - Top-Master