@import vs #import - iOS 7

jam*_*y25 428 import objective-c ios ios7

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

@import UIKit;
Run Code Online (Sandbox Code Playgroud)

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

nev*_*ing 836

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

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

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

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

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

在此输入图像描述

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;
Run Code Online (Sandbox Code Playgroud)

子模块在Xcode中自动完成.

  • @DaveDeLong&Klaas:谢谢!我必须承认,当我第一次回答这个问题时,我对模块一无所知.我去观看404会话来学习它.Doug Gregor(LLVM家伙)给出的演讲非常出色.还有一个C++模块讲座,其中解释了这里的优势:http://www.youtube.com/watch?v = 4Xo9iH5VLQ0 (14认同)
  • 如果提供了合适的module.map,我认为你应该能够@import第三方框架.LLVM clang模块文档:http://clang.llvm.org/docs/Modules.html#module-map-language (5认同)
  • @ nevan--谢谢你的回答.我只是想补充说,模块目前还不支持第三方和你自己的框架. (3认同)

gbk*_*gbk 46

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

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

#import "someFile.h"
Run Code Online (Sandbox Code Playgroud)

或者在框架的情况下:

#import <SomeLibrary/SomeFile.h>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

#import <SomeLibrary/SomeFile.h>
Run Code Online (Sandbox Code Playgroud)

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

@import SomeLibrary;
Run Code Online (Sandbox Code Playgroud)

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

@import AwesomeLibrary.AwesomeObject;
Run Code Online (Sandbox Code Playgroud)

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


yoA*_*ex5 7

@import 模块(ObjC) 或语义导入

而不是通常的模块使用

//as example
#include <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
Run Code Online (Sandbox Code Playgroud)

历史:

[#include -> #import] -> [预编译头文件.pch] -> @import 模块(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
Run Code Online (Sandbox Code Playgroud)

[Modulemap] - 模块和标头之间的桥梁

Xcode

Enable Modules(C and Objective-C)(CLANG_ENABLE_MODULES)- CLANG#include, #import指令会自动转换为@import带来所有优势的指令。Modulemap允许无缝完成,因为包含标头和子/模块之间的映射

经过-fmodules

#include, #import -> @import
Run Code Online (Sandbox Code Playgroud)

Link Frameworks Automatically(CLANG_MODULES_AUTOLINK)- 启用系统模块自动链接。需要激活CLANG_ENABLE_MODULES。自动链接允许-framework <framework_name>基于#import, @import(Objective-C), import(Swift)

如果否 - 通过-fno-autolink标志

CLANG_ENABLE_MODULES == NO 和 CLANG_MODULES_AUTOLINK == NO

如果您想手动#import <UIKit/UIKit.h>处理 system( ) 链接(而不是自动链接),您有两种变体:

  1. 添加依赖项到General -> Frameworks and Libraries or Frameworks, Libraries, and Embedded Content

  2. 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
Run Code Online (Sandbox Code Playgroud)
  • CLANG_ENABLE_MODULES被禁用
  • CLANG_MODULES_AUTOLINK已禁用且无需手动链接

逆向工程

otool -l <binary> 
//-l print the load commands
//find LC_LINKER_OPTION
//cmd LC_LINKER_OPTION
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

124363 次

最近记录:

6 年,1 月 前