在Objective-C中#import和#include之间有什么区别,有时候你应该使用一个而不是另一个吗?一个被弃用了吗?
我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble及其关于#import和#include的段落似乎自相矛盾或者至少不清楚.
关于预处理器似乎有很多混乱.
当编译器看到#include
它用所包含文件的内容替换该行时,编译器会做什么,没有问题.
所以如果你有一个a.h
包含这个内容的文件:
typedef int my_number;
和b.c
包含此内容的文件:
#include "a.h" #include "a.h"
b.c
在编译之前,预处理器将翻译该文件
typedef int my_number; typedef int my_number;
这将导致编译器错误,因为类型my_number
定义了两次.即使定义相同,C语言也不允许这样做.
由于头部经常在多个地方使用包括警卫通常在C.使用这看起来是这样的:
#ifndef _a_h_included_ #define _a_h_included_ typedef int my_number; #endif
b.c
在预处理之后,文件仍然会将标题的全部内容放入其中两次.但是第二个实例将被忽略,因为宏_a_h_included_
已经被定义了.
这非常有效,但有两个缺点.首先必须编写包含警戒,并且每个标题中的宏名称必须不同.其次,编译器仍然需要查找头文件并按原样读取它.
Objective-C有#import
预处理器指令(它也可以用于C和C++代码以及一些编译器和选项).这几乎#include
与之相同,但它也在内部记录了哪些文件已被包含在内.该#import
行仅在遇到第一次时被命名文件的内容替换.之后每次都被忽略了.
#import指令作为#include的改进版本添加到Objective-C中.然而,它是否得到改善仍然是一个争论的问题.#import确保文件只被包含一次,这样你就不会遇到递归包含问题.但是,大多数体面的头文件都可以保护自己不受此影响,所以它并没有那么大的好处.
基本上,由您决定要使用哪个.我倾向于#import标头用于Objective-C事物(比如类定义等)和#include标准C我需要的东西.例如,我的一个源文件可能如下所示:
#import#include #include
我同意杰森的观点.
我抓到了这样做:
#import// to use gettimeofday() function #import // to use time() function
对于GNU gcc,它一直抱怨没有定义time()函数.
然后我将#import改为#include,一切顺利.
原因:
#import
你#import
不行.尽管只包含
就#import而言,该文件现已完全包含在内.
底线:
C/C++传统上标头包括部件的其他包含文件.
因此,对于C/C++标头,请使用#include.
对于objc/objc ++标头,请使用#import.
#include
像C一样工作#include
.
#import
跟踪已包含哪些标头,如果在编译单元中多次导入标头,则会忽略这些标头.这使得不必使用标题保护.
底线只是#import
在Objective-C中使用,如果您的标题最终导入不止一次,请不要担心.
我知道这个线程很老......但是在"现代"......通过clang的@import
模块有一个更优越的"包含策略" - 这是经常被忽视的..
模块通过用更健壮,更有效的语义模型替换文本预处理器包含模型来改进对软件库API的访问.从用户的角度来看,代码看起来只是略有不同,因为一个使用导入声明而不是#include预处理器指令:
@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map
要么
@import Foundation; // Like #import@import ObjectiveC; // Like #import
但是,此模块导入的行为与相应的#include完全不同:当编译器看到上面的模块导入时,它会加载模块的二进制表示,并使其API直接可供应用程序使用.导入声明之前的预处理程序定义对提供的API没有影响...因为模块本身被编译为单独的独立模块.此外,导入模块时将自动提供使用该模块所需的任何链接器标志.此语义导入模型解决了预处理器包含模型的许多问题.
要启用模块,传递命令行标志-fmodules
又名CLANG_ENABLE_MODULES
中Xcode
-在编译时.如上所述..这种策略可以避免任何和所有LDFLAGS
.在中,您可以删除任何"OTHER_LDFLAGS"设置,以及任何"链接"阶段.
我发现编译/启动时间"感觉"更加快速(或者可能,"链接"时只有较少的延迟?)..而且,提供了清除现在无关的Project-Prefix.pch文件的绝佳机会,以及相应的构建设置GCC_INCREASE_PRECOMPILED_HEADER_SHARING
,GCC_PRECOMPILE_PREFIX_HEADER
以及GCC_PREFIX_HEADER
等
此外,虽然没有详细记录......您可以module.map
为自己的框架创建s并以相同的方式包含它们. 你可以看看我的ObjC-Clang-Modules github repo,了解如何实现这些奇迹的一些例子.