#import和#include在Objective-C中的区别是什么?在某些情况下你应该使用其中一个而不是另一个?一个被弃用了吗?

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


当前回答

#import指令作为#include的改进版本被添加到Objective-C中。然而,它是否有所改善仍是一个争论的问题。#import确保一个文件只被包含一次,这样就不会出现递归包含的问题。然而,大多数体面的头文件都会保护自己不受这种情况的影响,所以这并没有什么好处。

基本上,由您决定使用哪一种。我倾向于#import Objective-C内容(如类定义等)的头文件,#包含我需要的标准C内容。例如,我的一个源文件可能是这样的:

#import <Foundation/Foundation.h>

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

其他回答

我知道这个帖子很旧…但在“现代”…通过clang的@import模块有一个更优秀的“包含策略”-这经常被忽视。

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

@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.

要启用模块,在编译时传递命令行标志-fmodules,也就是Xcode中的CLANG_ENABLE_MODULES。如上所述…该策略避免了任何和所有ldflag。正如在,你可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..

我发现编译/启动时间“感觉”更迅速(或者可能,在“链接”时延迟更少?)..同时,也提供了一个很好的机会来清除现在多余的Project-Prefix。pch文件,以及相应的构建设置,gcc_incree_precompiled_header_sharing, GCC_PRECOMPILE_PREFIX_HEADER, GCC_PREFIX_HEADER等。

此外,虽然没有良好的文档…映射到您自己的框架,并以同样方便的方式包含它们。你可以看看我的ObjC-Clang-Modules github回购的一些例子,如何实现这样的奇迹。

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

#import "Class.h" 

类似于

{
#pragma once

#include "class.h"
}

这意味着当你的应用程序运行时,你的类只会被加载一次。

#include vs #import预处理器指令

历史:

#include -> #import ->[预编译Headers .pch] -> [@import Module(ObjC);] -> [import Module(Swift)]

#import是#include的下一代,它解决了当前.h文件的双重包含和递归包含问题。只是当前文件中包含的。h主体的单一副本

#import == #include + guard

守卫长这样

#ifndef <some_unique_name>
#define <some_unique_name>

<header_body>

#endif

#include guardWiki(宏保护,头保护,文件保护)-防止预处理器包含多个头,这会减慢构建时间

#include和#import使用了一种复制/粘贴机制——递归地复制.h文件主体(除了#include, #import指令之外的所有内容)。这意味着结果文件将不包含#include, #import指令)

如果选择。m文件Product -> Perform Action ->预处理“。m”,可以检查结果。

# include示例

//A.h
@interface A : NSObject
- (int)startA;
@end

//ViewController.h
#include "A.h"

ViewController。M预处理后

@interface A : NSObject
- (int)startA;

@end

@interface ViewController : UIViewController
@end

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

}
@end

双重包含示例

//A.h
@interface A : NSObject //Build time error: Duplicate interface definition for class 'A'
@end 

//B.h
#include "A.h"

//C.h
#include "A.h"
//#import "A.h" to solve
#include "B.h"

递归包含示例

//A.h
#include "B.h" //Build time error: #include nested too deeply
//#import "B.h" to fix it

@interface B : NSObject //Build time error: Duplicate interface definition for class 'A'
@end


//B.h 
#include "A.h" //Build time error: #include nested too deeply
//#import "A.h" to fix it

@interface B : NSObject //Build time error: Duplicate interface definition for class 'B'
@end

[#import in .h or .m]

在可能的情况下,我在我的.h文件中有一个全局变量,导致了这个问题,我通过在它前面添加extern来解决它。

#include就像c#中的include一样。

#import跟踪哪些头文件已经被包含,如果一个头文件在编译单元中被导入多次,则该头文件将被忽略。这使得没有必要使用头保护。

底线是在Objective-C中使用#import,不要担心你的头文件会导入一些东西不止一次。