@import与#import的对比- iOS 7

uyto3xhc  于 2022-12-24  发布在  iOS
关注(0)|答案(6)|浏览(224)

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

@import UIKit;

我想我在另一个会议视频中看到了一些关于这个的东西,但是我找不到它。我正在寻找关于何时使用这个的背景信息。它只能用于Apple框架吗?使用这个编译器指令的好处是否足以让我回去更新旧代码?

0s7z1bwu

0s7z1bwu1#

这是一个名为模块或“语义导入”的新功能。关于205404会话的WWDC 2013视频中有更多信息。这是一种更好的预编译头文件实现。您可以在iOS 7和Mavericks中的任何系统框架中使用模块。模块是框架可执行文件及其头文件的打包,被吹捧为比#import更安全、更高效。
使用@import的一大优势是
你不需要在项目设置中添加框架,它是自动完成的
。这意味着你可以跳过点击加号按钮并搜索框架(黄金工具箱)的步骤,然后将其移动到“Frameworks”组。这将使许多开发人员避免收到神秘的“Linker error”消息。

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

模块是为大多数Apple框架(UIKit、MapKit、GameKit等)预先构建的。您可以在自己创建的框架中使用它们:如果你在Xcode中创建Swift框架,它们会自动创建,你也可以为any Apple or 3rd-party library手动创建一个“.modulemap”文件。
您可以使用代码完成来查看可用框架的列表:

在Xcode 5的新项目中默认启用模块。要在旧项目中启用它们,请进入项目构建设置,搜索“Modules”并将“Enable Modules”设置为“YES”。“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中,子模块会自动完成。

cnwbcb6i

cnwbcb6i2#

你可以在《用Objective-C学习可可(ISBN:(电话:978-1-491- 90一三九-7)
模块是一种将文件和库包含并链接到项目中的新方法。要理解模块的工作原理及其优点,回顾Objective-C和#import语句的历史是很重要的。无论何时,当你想包含一个文件以供使用时,你通常会有一些代码,看起来像这样:

#import "someFile.h"

或者在框架的情况下:

#import <SomeLibrary/SomeFile.h>

因为Objective-C是C语言的超集,所以#import语句是C的#include语句的一个小的改进。编译时,它会将包含文件中的所有内容复制到代码中。2这有时会导致严重的问题。3例如,假设你有两个头文件:SomeFileA.hSomeFileB.h; SomeFileA.h包含SomeFileB.h,而SomeFileB.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语句了。

5t7ly7z5

5t7ly7z53#

  • @导入模块(ObjC)或语义导入*

而不是使用通常模块

//as example
#include <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
    • 历史记录:**

#include -> #import(https://stackoverflow.com/a/59212007/4770877)-〉Precompiled Headers .pch(https://stackoverflow.com/a/59213256/4770877)-〉@导入模块(对象C); - 〉import Module(Swift)(https://stackoverflow.com/a/67130959/4770877)
它是LLVM Modules的一部分
@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

Modulemap(https://stackoverflow.com/a/59213694/4770877)-模块和接头之间的桥接

    • X代码**

Enable Modules(C and Objective-C)(CLANG_ENABLE_MODULES)-CLANG #include, #import指令会自动转换为@import,这将带来所有优势。Modulemap允许无缝转换,因为它包含头文件和子/模块之间的Map
通过-fmodules

#include, #import -> @import

Link Frameworks Automatically(CLANG_MODULES_AUTOLINK)-启用系统模块自动链接。需要激活的CLANG_ENABLE_MODULES。自动链接允许基于#import, @import(Objective-C), import(Swift)传递-framework <framework_name>
如果否-通过-fno-autolink标志

    • 模块启动声响==否和模块自动链接声响==否**

如果要处理系统(#import <UIKit/UIKit.h>)链接手动(而不是自动链接),则有两种变体:
1.将依赖项添加到General -> Frameworks and Libraries or Frameworks, Libraries, and Embedded Content

  1. 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
7y4bm7vi

7y4bm7vi4#

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

4ngedf3f

4ngedf3f5#

似乎自XCode 7.x以来,在使用CLANG_ENABLE_MODULES启用clang模块时出现了大量警告
看一看Lots of warnings when building with Xcode 7 with 3rd party libraries

nsc4cvqm

nsc4cvqm6#

使用模块有几个好处。你只能在苹果的框架中使用它,除非创建了模块Map。@import有点类似于预编译头文件,当添加到.pch文件时,这是一种调整应用程序编译过程的方法。此外,你不必以旧的方式添加库,事实上,使用@import要快得多,效率也高得多。如果你还在寻找一本不错的参考书,我强烈推荐你阅读this article

相关问题