A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

黄铁军老师

初级黑马

  • 黑马币:

  • 帖子:

  • 精华:

© 黄铁军老师 初级黑马   /  2016-5-21 16:11  /  1014 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

大家好!我是深圳校区双元课堂的iOS导师--黄铁军。
因为在某一天带晚自习的时候,一位同学在做作业的时候遇到了一个类之间--循环依赖的问题,所以我想在这里和大家分享一下#import与@class。
OC中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用时的指针时,
如以下代码:

A.h文件
#import "B.h"
@interface A : NSObject
{
    B *_b;
}
@end

为了简单起见:A类是引用类,B类是被引用类,这里先不需要考虑A类的实现文件。

通常引用一个类有两种办法:
一种是通过 #import 方式引入;另一种是通过 @class 引入;

这两种的方式的区别在于:
1、#import 方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在 A.h 文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;
2、使用 @class 方式由于只需要只要被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用 #import 来包含被引用类的头文件;
通过上面2点也很容易知道在编译效率上,如果有上百个头文件都 #import 了同一个文件,或者这些文件一次被 #import (A->B,B->C,C->D...),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一边,这样的效率也是可想而知的,而相对来讲,使用 @class 方法就不会出现这种问题了。

对于循环依赖关系来说,比如A类引用B类,同时B类也引用A类
B类的代码:

B.h文件
#import "A.h"
@interface B : NSObject
{
    A *_a;
}
@end

这样子就出现类之间循环依赖引用了,这样子是不可以,编译就会出错。

B.h文件
@class A;
@interface B : NSObject
{
    A *_a;
}
@end

当使用 @class 声明的话,编译就不会出现错误。

由上可知,@class 是放在 interface 中的,只是在引用一个类,将这个被引用类作为一个类型,在实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用 #import 方式引入被引用类。

举个例子说明一下。
在 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
...
ClassB *pointer;

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

6 个回复

倒序浏览
学到,,,,
回复 使用道具 举报
长知识了。。。点赞。。。
回复 使用道具 举报
不错
回复 使用道具 举报
刚好解决我现在所遇到的问题
回复 使用道具 举报
干货
回复 使用道具 举报
铁军的威力感受到了,长知识了{:3_46:}
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马