#import的用法 - 在非常大的项目中使用#import的一般指导原则(ObjC)

时间:2013-02-21 16:41:34

标签: objective-c xcode dependencies header-files build-time

#import我的标题和实现在哪里?
关于我应该做什么的规则是什么? 有没有办法在单个头文件中导入所有内容?

4 个答案:

答案 0 :(得分:5)

鉴于“在非常大的项目中使用#import的一般指导原则。”。

嗯,在这方面,Objective-C很像C和C ++。将所有#include s / #import填入标题会引入大量不必要的依赖,这会为您的构建增加大量时间。因此,还可以在有关C和C ++依赖性的主题中寻求进一步的信息。

  

#import我的标题和实现在哪里?

通常,只应在物理依赖存在的地方编写#import。由于每个objc对象都是引用计数,并且标题中通常不需要存在属性/ ivars,因此#import远低于C ++。

Robin van Dijke在答案中概述了身体依赖的常见案例(+1)。

  

是否有关于我应该做什么的规则?   有没有办法在单个头文件中导入所有内容?

嗯,这取决于项目的大小。有些人将他们使用的所有框架添加到PCH(预编译头)。有些人把最常用的人放在PCH中,有些人根本不使用PCH文件。构建时间越长,项目越复杂,PCH应该包括的越少。

如果您正在处理“非常大”的项目,您可能不应该为您的PCH添加超过Foundation。

另一个常见错误是有些人会使用PCH,所以他们需要输入更少(相当多)。问题是他们的项目的常见包含/标题更改,当发生这种情况时,必须完全重建目标。

此外,如果您可以避免标题中的#import框架/库,则可以节省大量构建时间。

#import添加到标头会导致依赖关系进一步扩散。对于大量不相关的代码/框架来说很容易,只有少数源文件才能看到这些代码/框架对于大部分源文件实际可见。

最后,您应该尝试将经常更改的标头保留在其他标头之外。

最重要的是你应该:

  • 根据功能分离您的程序
  • 赞成#import的前瞻性声明。编译器必须知道名称,但只有在创建/发送对象时才需要导入。
  • 尝试将依赖性较大的实现保留在*.m文件中。

每隔一段时间,它可以帮助您查看某些源文件的预处理输出 - 看看实际上#import编辑的内容 - 结果可能会非常令人惊讶。

注意:

  • 必须为项目中的每种语言生成PCH。
  • 根据需要编制来源;例如如果您有C程序,请不要将它们编译为ObjC。
  • 随着项目复杂性的增加,通过划分目标(例如静态库,模块,逻辑划分测试......)所获得的收益将会增加。正确地构建具有低依赖性的依赖目标本身就是一个很大的主题。当结构正确时,它可以真正帮助您在更高频率下构建和测试(如果您使用持续集成或有多个开发人员,这也很重要)。像标题依赖项一样,如果你从一开始就不考虑这个问题,那么旧的问题可能需要花费大量的工时来纠正(在它已经变得难以忍受地变慢之后)。

答案 1 :(得分:3)

可以使用以下约定:

在标题文件中使用#import时 - 您对导入的类进行了子类化 - 您使用导入的头文件中的协议 - 您使用导入的头文件

中的其他C数据结构(枚举,结构)

示例:

#import "SuperClass.h"
#import "Protocol.h"

@class SomeOtherClass

@interface Subclass : SuperClass <Protocol>
    SomeOtherClass _instanceVariableToOtherClass
@end

否则在头文件中使用@class

对于所有其他情况,请在.m文件中使用#import

注意:#import "class.h"实际上是以下内容:

#pragma once
#include "class.h"

因此,每个类只需导入一次就可以防止包含循环/循环。

答案 2 :(得分:2)

First read this official site That may be helpful for you.

类似于#include语句C language

基本上#import语句有两个定义,

1) #import "headerFile.h" // This statement is use for Import any header file in current file (UIController)

2) #import<FramWorkName> // This statement basically use for add any framework in current file (UIController)

要使用项目中任何位置的任何文件,请在#import "fileName.h"中添加文件(.pch file)。 Prefix headers 被编译并存储在缓存中,然后在编译期间自动包含在每个文件中。这可以加快编译速度,并允许您包含文件而无需为使用它的每个文件添加import语句。它们不是必需的,并且每当您更改它们时实际上都会减慢编译速度。您的项目中.pch file extension提供了此文件。

喜欢这样:

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import "MyFile_Name.h"

您也可以使用PROTOCOL来定义其他类要实现的方法。

For More information about, How to create POTOCOL, here is Best example with detail.

答案 3 :(得分:0)

只是为了踢 - 我将添加一些“基本原则” - 尽管并不像已经说过的那样详细 - 有时可以帮助理解整个“过程”。

Implementation.m文件从不(据我所知#import'ed - 这就是编译器在“编译”时“正在”做的事情。

您希望所有已编译的文件(.m)文件“知道”可以放在.pch文件中。我通常也会在所有类中共享指令,即#import <Cocoa/Cocoa.h>等,因此我不必在每个文件中查看它们

如果您要在头文件中引用 以前未声明的类 ,即AppDelegate.h

@property (nonatomic, strong) HTTPServer *http;

可以 #import "HTTPServer.h" at the top of that file (or even in the。pch`)......但通常更好地引用“前瞻性课程”如下......

 @class HTTPServer;
 @interface AppDelegate : NSObject  ➜ ...

然后在#import "HTTPServer.h"的{​​{1}}文件中AppDelegate您需要访问到头文件的主要原因...是调用方法使用的属性等您自己的类“范围”中的外部类的实例。这就是为什么你可以“躲开”简单地“提及”标题中的.m - 你实际上还没有做任何事情。

唯一需要考虑的事情 - 如果您正在构建一个独立的应用程序,那么可能不是这种情况 - 但是在构建框架或捆绑等时...将引用您的类 < / em>在“API-kind-way-way”中......您可能希望在构建过程中添加“复制文件”阶段,这将允许“其他人”通过“公共标题”“了解”您的课程文件。在这种情况下......您可以简单地公开一个头文件,该头文件导入您的类所需的前向声明,而其他人则@class。这就是你能够访问“伞框架”中的所有类的方法,例如#import只有一个<Foundation/Foundation.h> ...它已经暴露了它首先“提供”的标题`.h'文件..á啦......

#import

如果您曾在Xcode之前使用过编译器,那么考虑它的方法是您需要导入的任何头与命令行上的“Include”#import <Foundation/NSArray.h> #import <Foundation/NSAutoreleasePool.h> 指令相同。给定头文件-I和源代码文件src/headers/header.h,它具有source.c语句..编译命令将是

#include "header.h"

通过导航到“日志导航器”和Xc​​ode并查看所有步骤,您可以了解在Xcode中编译内容时实际发生的情况。

xcode log