在Objective-C中,#import和#的区别是什么?

时间:2021-07-21 00:11:06

What are the differences between #import and #include in Objective-C and are there times where you should use one over the other? Is one deprecated?

在Objective-C中,#import和#的区别是什么?在哪里你应该用一个在另一个上面?是一个弃用吗?

I was reading the following tutorial: http://www.otierney.net/objective-c.html#preamble and its paragraph about #import and #include seems to contradict itself or at least is unclear.

我正在阅读下面的教程:http://www.otierney.net/objective-c.html#preamble,其关于#import和#的段落似乎自相矛盾,或者至少不清楚。

9 个解决方案

#1


324  

The #import directive was added to Objective-C as an improved version of #include. Whether or not it's improved, however, is still a matter of debate. #import ensures that a file is only ever included once so that you never have a problem with recursive includes. However, most decent header files protect themselves against this anyway, so it's not really that much of a benefit.

将#import指令添加到Objective-C中,作为#include的改进版本。然而,它是否有所改善仍是一个争论的话题。#导入确保文件只包含一次,这样您就不会遇到递归包含的问题。然而,大多数体面的头文件都保护自己不受此影响,所以这并不是真正的好处。

Basically, it's up to you to decide which you want to use. I tend to #import headers for Objective-C things (like class definitions and such) and #include standard C stuff that I need. For example, one of my source files might look like this:

基本上,由你来决定你想使用哪一个。对于Objective-C类的东西(比如类定义之类),我倾向于#import header,并且#包含了我需要的标准C。例如,我的一个源文件可能是这样的:

#import <Foundation/Foundation.h>

#include <asl.h>
#include <mach/mach.h>

#2


329  

There seems to be a lot of confusion regarding the preprocessor.

关于预处理器似乎有很多混乱。

What the compiler does when it sees a #include that it replaces that line with the contents of the included files, no questions asked.

当编译器看到一个#时,它会做什么,包括用包含的文件的内容替换这一行,没有问题。

So if you have a file a.h with this contents:

如果你有一个文件a。h与内容:

typedef int my_number;

and a file b.c with this content:

和一个文件b。c和这个内容:

#include "a.h"
#include "a.h"

the file b.c will be translated by the preprocessor before compilation to

文件b。c将在编译之前由预处理器翻译。

typedef int my_number;
typedef int my_number;

which will result in a compiler error, since the type my_number is defined twice. Even though the definition is the same this is not allowed by the C language.

这将导致编译器错误,因为类型my_number定义两次。即使定义是相同的,C语言是不允许的。

Since a header often is used in more than one place include guards usually are used in C. This looks like this:

由于标题通常在一个以上的地方使用,通常在c中使用了警卫。这看起来是这样的:

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

The file b.c still would have the whole contents of the header in it twice after being preprocessed. But the second instance would be ignored since the macro _a_h_included_ would already have been defined.

文件b。在预处理后,c仍然会有两次头的全部内容。但是第二个实例将被忽略,因为宏_a_h_included_已经被定义了。

This works really well, but has two drawbacks. First of all the include guards have to be written, and the macro name has to be different in every header. And secondly the compiler has still to look for the header file and read it as often as it is included.

这很有效,但有两个缺点。首先,必须编写包含的守卫,在每个标题中宏名称必须不同。其次,编译器仍然要查找头文件,并尽可能经常地读取它。

Objective-C has the #import preprocessor instruction (it also can be used for C and C++ code with some compilers and options). This does almost the same as #include, but it also notes internally which file has already been included. The #import line is only replaced by the contents of the named file for the first time it is encountered. Every time after that it is just ignored.

Objective-C有#import预处理器指令(它也可以用于C和c++代码和一些编译器和选项)。这几乎和#include一样,但它也在内部注意到已经包含了文件。第一次遇到的时候,#import行只被命名文件的内容替换。每次之后,它都被忽略了。

#3


61  

I agree with Jason.

我同意杰森。

I got caught out doing this:

我是这样做的:

#import <sys/time.h>  // to use gettimeofday() function
#import <time.h>      // to use time() function

For GNU gcc, it kept complaining that time() function was not defined.

对于GNU gcc,它一直抱怨时间()函数没有定义。

So then I changed #import to #include and all went ok.

然后我将#import更改为#include,然后一切正常。

Reason:

原因:

You #import <sys/time.h>:
    <sys/time.h> includes only a part of <time.h> by using #defines

你# < sys /导入时间。h >:< sys /时间。h>只包含 <时间的一部分。通过使用#定义h>

You #import <time.h>:
    No go. Even though only part of <time.h> was already included, as
    far as #import is concerned, that file is now already completely included.

你# <导入时间。h> :不去。即使只有一部分时间。h>已经包含,就#import而言,这个文件现在已经完全包含了。

Bottom line:

底线:

C/C++ headers traditionally includes parts of other include files.
So for C/C++ headers, use #include.
For objc/objc++ headers, use #import.

C/ c++头传统上包括其他包含文件的部分。所以对于C/ c++头,使用#include。对于objc/objc++头,使用#导入。

#4


22  

#include works just like the C #include.

包括和c#一样的工作。

#import keeps track of which headers have already been included and is ignored if a header is imported more than once in a compilation unit. This makes it unnecessary to use header guards.

#导入跟踪哪些头已经被包含,如果一个头在编译单元中被导入不止一次,则被忽略。这样就没有必要使用头守卫。

The bottom line is just use #import in Objective-C and don't worry if your headers wind up importing something more than once.

底线就是在Objective-C中使用#import,如果你的头不止一次导入,不要担心。

#5


11  

I know this thread is old... but in "modern times".. there is a far superior "include strategy" via clang's @import modules - that is oft-overlooked..

我知道这条线很旧……但在“摩登时代”。在clang的@import模块中有一个非常高级的“include策略”,这是经常被忽略的。

Modules improve access to the API of software libraries by replacing the textual preprocessor inclusion model with a more robust, more efficient semantic model. From the user’s perspective, the code looks only slightly different, because one uses an import declaration rather than a #include preprocessor directive:

模块通过将文本预处理器包含模型替换为更健壮、更高效的语义模型来改进对软件库API的访问。从用户的角度来看,代码看起来只是略有不同,因为使用的是import声明,而不是#include preprocessor指令:

@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map

or

@import Foundation;  //  Like #import <Foundation/Foundation.h>
@import ObjectiveC;  //  Like #import <objc/runtime.h>

However, this module import behaves quite differently from the corresponding #include: when the compiler sees the module import above, it loads a binary representation of the module and makes its API available to the application directly. Preprocessor definitions that precede the import declaration have no impact on the API provided... because the module itself was compiled as a separate, standalone module. Additionally, any linker flags required to use the module will automatically be provided when the module is imported. This semantic import model addresses many of the problems of the preprocessor inclusion model.

但是,这个模块导入的行为与相应的#include有很大的不同:当编译器看到上面的模块导入时,它会加载模块的二进制表示,并使它的API直接用于应用程序。在导入声明之前的预处理器定义对所提供的API没有影响…因为模块本身被编译成一个独立的独立模块。此外,在导入模块时,将自动提供使用该模块所需的任何链接器标志。这种语义导入模型解决了预处理器包含模型的许多问题。

To enable modules, pass the command-line flag -fmodules aka CLANG_ENABLE_MODULES in Xcode- at compile time. As mentioned above.. this strategy obviates ANY and ALL LDFLAGS. As in, you can REMOVE any "OTHER_LDFLAGS" settings, as well as any "Linking" phases..

要启用模块,可以在编译时将命令行标记-fmodules -fmodules,也就是Xcode中的CLANG_ENABLE_MODULES。正如上面提到的. .这种策略消除了任何和所有的LDFLAGS。例如,您可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段。

在Objective-C中,#import和#的区别是什么?

I find compile / launch times to "feel" much snappier (or possibly, there's just less of a lag while "linking"?).. and also, provides a great opportunity to purge the now extraneous Project-Prefix.pch file, and corresponding build settings, GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER, and GCC_PREFIX_HEADER, etc.

我发现编译/发布时间会“感觉”更敏捷(或者可能,“链接”的时候不那么滞后)。同时,也提供了一个很好的机会来清除现在无关的项目前缀。pch文件,以及相应的构建设置,gcc_递增e_precompiled_header_sharing, GCC_PRECOMPILE_PREFIX_HEADER和GCC_PREFIX_HEADER等。

Also, while not well-documented… You can create module.maps for your own frameworks and include them in the same convenient fashion. You can take a look at my ObjC-Clang-Modules github repo for some examples of how to implement such miracles.

此外,虽然没有充分的文档说明……您可以创建模块。映射您自己的框架,并以同样方便的方式包含它们。您可以看一下我的ObjC-Clang-Modules模块github repo,看看如何实现这些奇迹。

#6


3  

If you are familiar with C++ and macros, then

如果您熟悉c++和宏,那么。

#import "Class.h" 

is similar to

类似于

{
#pragma once

#include "class.h"
}

which means that your Class will be loaded only once when your app runs.

这意味着您的类只在应用程序运行时加载一次。

#7


1  

IF you #include a file two times in .h files than compiler will give error. But if you #import a file more than once compiler will ignore it.

如果在.h文件中包含一个文件两次,编译器将会出错。但是如果您导入一个文件,编译器会忽略它。

#8


1  

In may case I had a global variable in one of my .h files that was causing the problem, and I solved it by adding extern in front of it.

在5月份的时候,我的一个。h文件中有一个全局变量,导致了这个问题,我通过在它前面加上外部来解决它。

#9


0  

#include it used to get "things" from another file to the one the #include is used in. Ex:

#include用于从另一个文件获取“东西”到#include所使用的内容。例:

in file: main.cpp

在文件:main.cpp

#include "otherfile.h"

// some stuff here using otherfile.h objects,
// functions or classes declared inside

Header guard is used on the top of each header file (*.h) to prevent including the same file more then once (if it happens you will get compile errors).

在每个头文件(*.h)的顶部都使用了头部保护,以防止再次包含相同的文件(如果发生的话,您将会得到编译错误)。

in file: otherfile.h

在文件:otherfile.h

#ifndef OTHERFILE
#define OTHERFILE

// declare functions, classes or objects here

#endif

even if you put #include "otherfile.h" n time in your code, this inside it will not be redeclared.

即使你放了#include“otherfile”。在你的代码中,这段代码将不会被重新声明。

#1


324  

The #import directive was added to Objective-C as an improved version of #include. Whether or not it's improved, however, is still a matter of debate. #import ensures that a file is only ever included once so that you never have a problem with recursive includes. However, most decent header files protect themselves against this anyway, so it's not really that much of a benefit.

将#import指令添加到Objective-C中,作为#include的改进版本。然而,它是否有所改善仍是一个争论的话题。#导入确保文件只包含一次,这样您就不会遇到递归包含的问题。然而,大多数体面的头文件都保护自己不受此影响,所以这并不是真正的好处。

Basically, it's up to you to decide which you want to use. I tend to #import headers for Objective-C things (like class definitions and such) and #include standard C stuff that I need. For example, one of my source files might look like this:

基本上,由你来决定你想使用哪一个。对于Objective-C类的东西(比如类定义之类),我倾向于#import header,并且#包含了我需要的标准C。例如,我的一个源文件可能是这样的:

#import <Foundation/Foundation.h>

#include <asl.h>
#include <mach/mach.h>

#2


329  

There seems to be a lot of confusion regarding the preprocessor.

关于预处理器似乎有很多混乱。

What the compiler does when it sees a #include that it replaces that line with the contents of the included files, no questions asked.

当编译器看到一个#时,它会做什么,包括用包含的文件的内容替换这一行,没有问题。

So if you have a file a.h with this contents:

如果你有一个文件a。h与内容:

typedef int my_number;

and a file b.c with this content:

和一个文件b。c和这个内容:

#include "a.h"
#include "a.h"

the file b.c will be translated by the preprocessor before compilation to

文件b。c将在编译之前由预处理器翻译。

typedef int my_number;
typedef int my_number;

which will result in a compiler error, since the type my_number is defined twice. Even though the definition is the same this is not allowed by the C language.

这将导致编译器错误,因为类型my_number定义两次。即使定义是相同的,C语言是不允许的。

Since a header often is used in more than one place include guards usually are used in C. This looks like this:

由于标题通常在一个以上的地方使用,通常在c中使用了警卫。这看起来是这样的:

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

The file b.c still would have the whole contents of the header in it twice after being preprocessed. But the second instance would be ignored since the macro _a_h_included_ would already have been defined.

文件b。在预处理后,c仍然会有两次头的全部内容。但是第二个实例将被忽略,因为宏_a_h_included_已经被定义了。

This works really well, but has two drawbacks. First of all the include guards have to be written, and the macro name has to be different in every header. And secondly the compiler has still to look for the header file and read it as often as it is included.

这很有效,但有两个缺点。首先,必须编写包含的守卫,在每个标题中宏名称必须不同。其次,编译器仍然要查找头文件,并尽可能经常地读取它。

Objective-C has the #import preprocessor instruction (it also can be used for C and C++ code with some compilers and options). This does almost the same as #include, but it also notes internally which file has already been included. The #import line is only replaced by the contents of the named file for the first time it is encountered. Every time after that it is just ignored.

Objective-C有#import预处理器指令(它也可以用于C和c++代码和一些编译器和选项)。这几乎和#include一样,但它也在内部注意到已经包含了文件。第一次遇到的时候,#import行只被命名文件的内容替换。每次之后,它都被忽略了。

#3


61  

I agree with Jason.

我同意杰森。

I got caught out doing this:

我是这样做的:

#import <sys/time.h>  // to use gettimeofday() function
#import <time.h>      // to use time() function

For GNU gcc, it kept complaining that time() function was not defined.

对于GNU gcc,它一直抱怨时间()函数没有定义。

So then I changed #import to #include and all went ok.

然后我将#import更改为#include,然后一切正常。

Reason:

原因:

You #import <sys/time.h>:
    <sys/time.h> includes only a part of <time.h> by using #defines

你# < sys /导入时间。h >:< sys /时间。h>只包含 <时间的一部分。通过使用#定义h>

You #import <time.h>:
    No go. Even though only part of <time.h> was already included, as
    far as #import is concerned, that file is now already completely included.

你# <导入时间。h> :不去。即使只有一部分时间。h>已经包含,就#import而言,这个文件现在已经完全包含了。

Bottom line:

底线:

C/C++ headers traditionally includes parts of other include files.
So for C/C++ headers, use #include.
For objc/objc++ headers, use #import.

C/ c++头传统上包括其他包含文件的部分。所以对于C/ c++头,使用#include。对于objc/objc++头,使用#导入。

#4


22  

#include works just like the C #include.

包括和c#一样的工作。

#import keeps track of which headers have already been included and is ignored if a header is imported more than once in a compilation unit. This makes it unnecessary to use header guards.

#导入跟踪哪些头已经被包含,如果一个头在编译单元中被导入不止一次,则被忽略。这样就没有必要使用头守卫。

The bottom line is just use #import in Objective-C and don't worry if your headers wind up importing something more than once.

底线就是在Objective-C中使用#import,如果你的头不止一次导入,不要担心。

#5


11  

I know this thread is old... but in "modern times".. there is a far superior "include strategy" via clang's @import modules - that is oft-overlooked..

我知道这条线很旧……但在“摩登时代”。在clang的@import模块中有一个非常高级的“include策略”,这是经常被忽略的。

Modules improve access to the API of software libraries by replacing the textual preprocessor inclusion model with a more robust, more efficient semantic model. From the user’s perspective, the code looks only slightly different, because one uses an import declaration rather than a #include preprocessor directive:

模块通过将文本预处理器包含模型替换为更健壮、更高效的语义模型来改进对软件库API的访问。从用户的角度来看,代码看起来只是略有不同,因为使用的是import声明,而不是#include preprocessor指令:

@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map

or

@import Foundation;  //  Like #import <Foundation/Foundation.h>
@import ObjectiveC;  //  Like #import <objc/runtime.h>

However, this module import behaves quite differently from the corresponding #include: when the compiler sees the module import above, it loads a binary representation of the module and makes its API available to the application directly. Preprocessor definitions that precede the import declaration have no impact on the API provided... because the module itself was compiled as a separate, standalone module. Additionally, any linker flags required to use the module will automatically be provided when the module is imported. This semantic import model addresses many of the problems of the preprocessor inclusion model.

但是,这个模块导入的行为与相应的#include有很大的不同:当编译器看到上面的模块导入时,它会加载模块的二进制表示,并使它的API直接用于应用程序。在导入声明之前的预处理器定义对所提供的API没有影响…因为模块本身被编译成一个独立的独立模块。此外,在导入模块时,将自动提供使用该模块所需的任何链接器标志。这种语义导入模型解决了预处理器包含模型的许多问题。

To enable modules, pass the command-line flag -fmodules aka CLANG_ENABLE_MODULES in Xcode- at compile time. As mentioned above.. this strategy obviates ANY and ALL LDFLAGS. As in, you can REMOVE any "OTHER_LDFLAGS" settings, as well as any "Linking" phases..

要启用模块,可以在编译时将命令行标记-fmodules -fmodules,也就是Xcode中的CLANG_ENABLE_MODULES。正如上面提到的. .这种策略消除了任何和所有的LDFLAGS。例如,您可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段。

在Objective-C中,#import和#的区别是什么?

I find compile / launch times to "feel" much snappier (or possibly, there's just less of a lag while "linking"?).. and also, provides a great opportunity to purge the now extraneous Project-Prefix.pch file, and corresponding build settings, GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER, and GCC_PREFIX_HEADER, etc.

我发现编译/发布时间会“感觉”更敏捷(或者可能,“链接”的时候不那么滞后)。同时,也提供了一个很好的机会来清除现在无关的项目前缀。pch文件,以及相应的构建设置,gcc_递增e_precompiled_header_sharing, GCC_PRECOMPILE_PREFIX_HEADER和GCC_PREFIX_HEADER等。

Also, while not well-documented… You can create module.maps for your own frameworks and include them in the same convenient fashion. You can take a look at my ObjC-Clang-Modules github repo for some examples of how to implement such miracles.

此外,虽然没有充分的文档说明……您可以创建模块。映射您自己的框架,并以同样方便的方式包含它们。您可以看一下我的ObjC-Clang-Modules模块github repo,看看如何实现这些奇迹。

#6


3  

If you are familiar with C++ and macros, then

如果您熟悉c++和宏,那么。

#import "Class.h" 

is similar to

类似于

{
#pragma once

#include "class.h"
}

which means that your Class will be loaded only once when your app runs.

这意味着您的类只在应用程序运行时加载一次。

#7


1  

IF you #include a file two times in .h files than compiler will give error. But if you #import a file more than once compiler will ignore it.

如果在.h文件中包含一个文件两次,编译器将会出错。但是如果您导入一个文件,编译器会忽略它。

#8


1  

In may case I had a global variable in one of my .h files that was causing the problem, and I solved it by adding extern in front of it.

在5月份的时候,我的一个。h文件中有一个全局变量,导致了这个问题,我通过在它前面加上外部来解决它。

#9


0  

#include it used to get "things" from another file to the one the #include is used in. Ex:

#include用于从另一个文件获取“东西”到#include所使用的内容。例:

in file: main.cpp

在文件:main.cpp

#include "otherfile.h"

// some stuff here using otherfile.h objects,
// functions or classes declared inside

Header guard is used on the top of each header file (*.h) to prevent including the same file more then once (if it happens you will get compile errors).

在每个头文件(*.h)的顶部都使用了头部保护,以防止再次包含相同的文件(如果发生的话,您将会得到编译错误)。

in file: otherfile.h

在文件:otherfile.h

#ifndef OTHERFILE
#define OTHERFILE

// declare functions, classes or objects here

#endif

even if you put #include "otherfile.h" n time in your code, this inside it will not be redeclared.

即使你放了#include“otherfile”。在你的代码中,这段代码将不会被重新声明。