一、#import和#include的区别当我们在代码中使用两次#include的时候会报错:因为#include相当于拷贝头文件中的声明内容,所以会报重复定义的错误
但是使用两次#import的话,不会报错,所以他可以解决重复导入的问题,他会做一次判断,如果已经导入一次就不导入了
二、关键字@class的作用在来看一下OC中的关键字@class的作用,在看他的作用之前,先来看一个问题:
现在有一个课程类Classes和学生类Student,他们两之间需要
相互引用(导入)。直接看代码比较直接:
Classes.h[objc] view plaincopy 1. //
2. // Classes.h
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Student.h"
12.
13. //不会将Student.h拷贝过来,只是告诉编译器Student这个类在别的地方中有定义,这样就不知道这个类中任何信息(哪些属性和方法)
14. //@class Student;
15.
16.
@interface Classes : NSObject{
17.
18.
@public 19.
Student *_student;
20. }
21.
22. - (
void)t1;
23.
24.
@end 导入Student.h头文件
Classes.m[objc] view plaincopy 1. //
2. // Classes.m
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import "Classes.h"
10.
11. //#import "Student.h"
12.
13.
@implementation Classes
14.
15. - (
void)t1{
16. [_student work];
17. }
18.
19.
@end 在来看一下Student类
Student.h[objc] view plaincopy 1. // Student.h
2. // 08_@class
3. //
4. // Created by jiangwei on 14-10-11.
5. // Copyright (c) 2014年 jiangwei. All rights reserved.
6. //
7.
8. #import <Foundation/Foundation.h>
9.
10. #import "Classes.h"
11.
12.
@interface Student : NSObject{
13.
Classes *_classes;
14. }
15.
16. - (
void)work;
17.
18.
@end 同样的也导入Classes.h头文件
Student.m[objc] view plaincopy 1. //
2. // Student.m
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import "Student.h"
10.
11.
@implementation Student
12.
13. - (
void)work{
14. NSLog(@"work");
15. }
16.
17.
@end 在来看一下测试代码:
main.m[objc] view plaincopy 1. //
2. // main.m
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. #import "Classes.h"
12. #import "Student.h"
13.
14. //Classes和Student相互导入会出现问题
15. //这时候我们就可以使用@class解决这样的问题
16. //我们一般在.h文件中使用@class,因为在.h文件中一般是不会使用类的属性和方法的
17. //在.m文件中可以导入.h文件
18.
int main(
int argc,
const charchar * argv[]) {
19.
@autoreleasepool {
20.
Classes *cls =[[Classes alloc] init];
21.
Student *stu = [[Student alloc] init];
22. cls->_student = stu;
23. [cls t1];
24.
25. }
26.
return 0;
27. }
这里有一个问题注意一下:
我们看到了这里是如何使用Classes中的属性_student的,因为在Classes类中属性_student是@public的,所以可以直接使用,用的是箭头符号,和C/C++中的指针变量调用差不多。记住了,这里就说到了如何直接访问一个类中的@public修饰符的属性变量我们编译运行:
看到了,编译错误,说在Student类中的Classes类找不到指定类型,这就奇怪了,我们不是导入了Classes.h文件了,为什么还是找不到类型呢?
这就是OC中类的相互引用的问题,我们在Student.h文件中导入了Classes.h,又在Classes.h文件中导入了Student.h,OC中在相互导入的时候编译是不通过的
这样就会导致错误。
当然解决办法就是使用
@class关键字,我们修改一下Classes类
Classes.h[objc] view plaincopy 1. //
2. // Classes.h
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import <Foundation/Foundation.h>
10.
11. //#import "Student.h"
12.
13. //不会将Student.h拷贝过来,只是告诉编译器Student这个类在别的地方中有定义,这样就不知道这个类中任何信息(哪些属性和方法)
14.
@class Student;
15.
16.
@interface Classes : NSObject{
17.
18.
@public 19.
Student *_student;
20. }
21.
22. - (
void)t1;
23.
24.
@end 我们将#import "Student.h"代码注释了,使用
@class Student这段代码的作用就是不会将Student.h文件拷贝过来,只是告诉编译器Student这个类在别的地方中有定义,这样就不知道这个类中的任何信息了(哪些属性和方法)
Classes.m[objc] view plaincopy 1. //
2. // Classes.m
3. // 08_@class
4. //
5. // Created by jiangwei on 14-10-11.
6. // Copyright (c) 2014年 jiangwei. All rights reserved.
7. //
8.
9. #import "Classes.h"
10.
11. #import "Student.h"
12.
13.
@implementation Classes
14.
15. - (
void)t1{
16. [_student work];
17. }
18.
19. @end