0

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

4

4 回答 4

6

鉴于“在大型项目中使用#import 的一般准则。 ”。

嗯,Objective-C 在这方面很像 C 和 C++。将所有#includes/ #imports 填充到您的标头中会引入许多不必要的依赖关系,这会为您的构建增加大量时间。因此,还可以在有关 C 和 C++ 依赖项的主题中寻求更多信息。

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

通常,您应该#import只在存在物理依赖的地方编写。由于每个 objc 对象都进行了引用计数,并且您的属性/变量通常不需要存在于标头中,因此#imports 远低于 C++。

Robin van Dijke 在他的回答 (+1) 中概述了身体依赖的常见情况。

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

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

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

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

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

向标头添加#imports 会导致依赖关系进一步扩散。大量不相关的代码/框架很容易对一些源文件可见,而实际上对大部分源文件可见。

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

最大的收获是你应该:

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

每隔一段时间,它可以帮助检查一些源文件的预处理输出——看看实际#import编辑了什么——结果可能会非常令人惊讶。

笔记:

  • 必须为项目中的每种语言生成 PCH。
  • 根据需要编译源代码;例如,如果您有 C 程序,请不要将它们编译为 ObjC。
  • 随着项目复杂性的增加,除以目标(例如静态库、模块、逻辑划分测试......)所获得的收益将会增加。以低依赖性正确构建依赖目标本身就是一个很大的话题。如果结构正确,它确实可以帮助您以更高的频率构建和测试(如果您使用持续集成或拥有多个开发人员,这也很重要)。就像头文件依赖一样,如果您从一开始就没有考虑到这一点,那么旧问题可能需要花费大量工时来纠正(在它已经变得难以忍受的缓慢之后)。
于 2013-03-06T06:48:43.943 回答
3

可以使用以下约定:

在以下情况下在头文件中使用#import- 您对导入的类进行子类化 - 您使用来自导入的头文件的协议 - 您使用来自导入的头文件的其他 C 数据结构(枚举、结构)

例子:

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

@class SomeOtherClass

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

否则@class在头文件中使用

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

注:#import "class.h"其实是这样的:

#pragma once
#include "class.h"

因此,请注意每个类只导入一次以防止包含循环/循环。

于 2013-03-05T08:33:34.093 回答
2

首先阅读这个官方网站,这可能对你有帮助。

它类似于,#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 头文件被编译并存储在缓存中,然后在编译期间自动包含在每个文件中。这可以加快编译速度,并允许您包含一个文件,而无需向使用它的每个文件添加导入语句。它们不是必需的,而且每次更改它们时编译速度实际上都很慢。此文件在您的项目中可用.pch file extension

像这样:

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

您还可以使用PROTOCOLfor 定义要由其他类实现的方法。

有关如何创建的更多信息POTOCOL,这里是详细的最佳示例。

于 2013-03-05T11:45:28.753 回答
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"AppDelegate's.m文件中。您需要访问头文件的主要原因......是在您自己的类的“范围”内调用该外部类的实例的方法和使用属性等。这就是为什么你可以简单地在你的标题中“提及”“逃脱” - 你实际上还没有对它做任何事情。@class

唯一需要考虑的另一件事 - 如果您正在构建独立应用程序,这可能不是这种情况 - 但是在构建框架或捆绑包等时......您的类在“API-kind- of-way”……您可能希望在构建过程中添加一个“复制文件”阶段,这将允许“其他人”通过您的“公共头文件”文件“了解”您的类。在这种情况下......您可以简单地公开一个头文件,该文件导入您的类所需的前向声明,供其他人使用#import. 这就是您能够访问“伞形框架”中所有类的方式,例如<Foundation/Foundation.h>使用单个#import......它在第一个“.h”文件中公开了它“可用”的标题...... á la。 .

#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>

如果您曾经在 Xcode 之前使用过编译器,那么考虑它的方式是,您需要导入的任何标头都与-I命令行上的“包含”指令相同。给定一个头文件和一个包含语句src/headers/header.h的源代码文件..编译命令将是source.c#include "header.h"

gcc -Iheaders/ source.c -o executable

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

代码日志

于 2013-03-07T18:59:37.630 回答