iOS 中 #import 和 @class 的区别

1.#import 会包含这个类的所有信息,包括实体变量和方法,而 @class 只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。

2.在头文件(.h 文件)中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用 @class 来声明这个名称是类的名称。 而在实现类(.m 文件)里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用 #import 来包含这个被引用类的头文件。

3.在编译效率方面考虑,如果你有100个头文件都 #import 了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而用 @class 则不会。

4.如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系,如果使用 #import 来相互包含,那么就会出现编译错误,如果使用 @class 在两个类的头文件中相互声明,则不会有编译错误出现。

所以,一般来说,@class 是放在 .h文件中的,只是为了在 .h文件中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的 .m文件中,如果需要引用这个类的实体变量或者方法之类的,还是需要 #import在@class中声明的类进来.

举个例子说明一下。

在ClassA.h中
#import ClassB.h 相当于#include整个.h头文件。如果有很多.m文件#import
ClassA.h,那么编译的时候这些文件也会 #import
ClassB.h 增加了没必要的 #import,浪费编译时间。在大型软件中,减少 .h文件中的 #include是非常重要的。
如果,只是 ClassB 那就没有 #include
ClassB.h。仅需要在需要用到 ClassB的 .m 文件中 #import ClassB.h

那么什么时候可以用呢?
如果 ClassA.h 中仅需要声明一个 ClassB 的指针,那么就可以在 ClassA.h 中声明 @ClassB;

假设,有两个类:ClassA和ClassB,两个之间相互使用到,即构成了circular
dependency(循环依赖)。如果在头文件里面只用 #import 把对方的头文件包含进来(构成circular
inclusions,循环包含),则编译器会报错:

Expected specifier-qualifier-list before ‘ClassA’

或者

Expected specifier-qualifier-list before ‘ClassB’

为了避免循环包含,在ClassA.h文件里面用 @class ClassB; 把 ClassB 包含进来,同样,在 ClassB.h 文件里面用 @class
ClassA  把 ClassA 包含进来。@class指令只是告诉编译器,这是个类,保留个空间来存放指针就可以了。接下来,很可能在 ClassA.m 和 ClassB.m 中会有访问包含进来对象的成员的情况,这时必须让编译器知道更多信息,比如那个类有些什么方法可以调用,就必须用 #import,再次把用到的类包含进来,告诉编译器所需要的额外信息。否则,编译器会警告:

warning: receiver ‘ClassA’ is a forward class and
corresponding @interface may not exist

还有另一种情况,使用有 Categories 的类,要在 .h头文件里用 #import 把 Categories 包含进来。

总之,使用原则是:

头文件里面只 #import 超类 消息文件里面 #import 需要发消息过去的类
其他地方就用 @class 转向声明

时间: 2024-11-06 14:15:30

iOS 中 #import 和 @class 的区别的相关文章

objective-c中#import和@class的区别

在Objective-C中,可以使用#import和@class来引用别的类型, 但是你知道两者有什么区别吗? @class叫做forward-class,  你经常会在头文件的定义中看到通过@class的引用, 原因就是当你只用@class来引入一个类时, 编译器知道有这么一个类,也就是说它能识别Engine *engine; 而在implementation文件中,如果你想要访问engine.price, 编译器就会出错, 即使你用了@class引入了. 这时需要使用的其实是#import

IOS中Retain和Copy的区别

IOS中Retain和Copy的区别 1 ,可读性: readonly  . readwrite@property(readwrite,....) valueType value;这个属性是变量的默认属性,就是如果你 (readwrite and readonly 都没有使用,那么你的变量就是 readwrite 属性 ) ,通过加入 readwrite 属性你的变量就会有 get 方法,和 set 方法.property(readonly,...) valueType value;这个属性变量

js中import和require的区别

js中import和require的区别ES6标准发布后,module成为标准,标准使用是以export指令导出接口,以import引入模块.但是在我们一贯的node模块中,我们依然采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口. require它相当于module.exports的传送门,module.exports后面的内容是什么,require的结果就是什么,对象.数字.字符串.函数……再把require的结果赋值给某个变量,相当于把re

iOS 中 #import同@class之间的区别

很多刚开始学习iOS开发的同学可能在看别人的代码的时候会发现有部分#import操作写在m文件中,而h文件仅仅使用@class进行声明,不禁纳闷起来,为什么不直接把#import放到h文件中呢? 这是因为h文件在修改后,所有import该h文件的所有文件必须重 新build,因此,如果把#import写在h文件中,import该h文件的文件也就会产生不必要的编译,增加编译时间,特别是在项目文件多的情况 下.想象一下,如果只是修改一个h文件而导致上百个文件不必要的编译,那是一件多么让人纠结的事情.

python中import和from-import的区别

. import导入模块的路径两种方式 # 将模块所在路径再程序中添加到sys.path列表中 import sys sys.path import导入模块按照sys.path顺序依次查找,""代表当前路径 # 修改操作系统的PYTHON_PATH环境变量 # 系统的环境变量 export PYTHON_PATH=$PYTHON_PATH:新的路径 . import 模块名 和 from 模块名 import * 是不同的; 1. 调用模块属性的区别 import 模块名 模块名.xx

Objective-C 中 #import 和 #include 的区别

预编译指令Objective-C:#importC,C++:#include#import由gcc编译器支持 在 Objective-C 中,#import 被当成 #include 指令的改良版本来使用.除此之外,#import 确定一个文件只能被导入一次,这使你在递归包含中不会出现问题. 使用哪一个还是由你来决定.一般来说,在导入 Objective-C 头文件的时候使用 #import,包含 C 头文件时使用 #include.比如: #import #include#include #i

一张图让你明白IOS中bounds和frame的区别

很多人在学习的就搞混了bounds和frame的区别,大家可以看看这张图就会明白它俩的区别: frame: 该view在父view坐标系统中的位置和大小.(参照点是,父亲的坐标系统) bounds:该view在本地坐标系统中的位置和大小.(参照点是,本地坐标系统,就相当于ViewB自己的坐标系统,以0,0点为起点) center:该view的中心点在父view坐标系统中的位置和大小.(参照点是,父亲的坐标系统) 看上图中,如果将ViewA的bounds设置为(-200,-100,550,400)

iOS中堆和栈的区别

堆和栈的区别主要有以下五点: 1.管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来讲,释放工作由程序员控制,容易产生memory leak(内存泄露). 2.申请大小: 栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,是一个编译时就确定的常数,如果申请空间超过栈的剩余空间时,将提示overflow(溢出).因此,能从栈获得的空间较小. 堆是向高地址扩展的数据结构,是不连续的内存区域.这是由于系统是由链表来存储的空闲内

【原】iOS中KVC和KVO的区别

在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间接访问实例变量的方法. KVC 提供了一个使用字符串(Key)而不是访问器方法,去访问一个对象实例变量的机制. 2> KVC部分源码(头文件) 1 // NSKeyValueCoding.h 2 @interface NSObject(NSKeyValueCoding) 3 4 + (BOOL)acce