前言
寒假分享会的遗漏问题总结
引入
在C/CPP语言里,引入某个头文件的操作
#include<iostream>
#include<string>
也有
#include "string"
同样在OC里面 引入某个类会用到 #import关键字
#import "LoginViewController.h"
#import "LoginView.h"
#import "RegisterViewController.h"
或者
#import <AFNetworking.h>
在寒假学习优化代码的时候知道了向前声明@Class
操作,区分和学习一下它们三个。
import 和 @class区别
在iOS中我们经常会在.h和.m中引入一些类啊等等一般用的是#import来进行声明,可能也见到在.h文件进用@class来声明的,那么#import和@class进行声明 到底有什么的区别呢?
import
import会包含这个类的所有信息,包括实体变量和方法(.h文件中),而@class
只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,后面会再告诉你。(在头文件中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import
来包含这个被引用类的头文件。)
#import
就是把被引用类的头文件走一遍,即把.h文件里的变量和方法包含进来一次,且仅一次,而@class不用,所以后者编译效率更高。
在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。
@class则不会。
@class
只是简单的一个声明告编译器有这个类不让其报错,那么.m中要用到引入的类的方法和属性时,不还是要#import头文件一次,是的这个是对的,但编译器编译的时候只编译头文件的,所以你的.m中用#import与编译时间没太大关系
有ClassA ClassB,在B里面想初始化A,必须使用import.
当你只需要声明某个类在h文件的时候@Class一般更加高效。当然,在m文件里面使用它的时候需要import它的h文件。
使用场景
就是如果有循环依赖关系,如:A->B,B->A这样相互依赖时,如果在两个文件的头文件中用#import分别声明对方,那么就会出现头文件循环利用的错误
// ClassA.h
#import "ClassB.h"
@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *b;
@end
// ClassB.h
#import "ClassA.h"
@interface ClassB : NSObject
@property (nonatomic, strong) ClassA *a;
@end
在循环引用中,如果使用了#import导入头文件,会导致编译器无法正确处理类的依赖关系,从而出现“找不到类”的问题。这是因为#import是将整个头文件内容拷贝到导入文件的位置,而不是简单的引用头文件。当存在循环引用时,两个类的头文件都会相互导入,导致头文件中出现重复的类定义,进而导致编译错误。
使用@class ClassB即可
// ClassA.h
@class ClassB;
@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *b;
@end
// ClassB.h
@class ClassA;
@interface ClassB : NSObject
@property (nonatomic, strong) ClassA *a;
@end
当编译器遇到@class ClassB时,会知道ClassB类的存在,而不会引起循环引用的问题。在实现文件中,通过#import导入ClassB类的头文件,即可使用ClassB类的定义。
总之,@class关键字可以在解决类的循环引用问题时起到重要的作用,它可以让编译器知道类的存在,而不会引起循环引用的问题。
继承使用import
当一个类需要继承另一个类时,可以使用#import来引入基类的头文件,并使得基类的定义在派生类中可见
// MyClass.h
#import "MyBaseClass.h"
@interface MyClass : MyBaseClass
// ...
@end
include<> 和 include""
#include是一个预处理指令,用于将一个文件的内容插入到当前文件中。
- #include :用于包含标准库的头文件,这些头文件通常位于编译器的系统目录中。使用<>来包含头文件,编译器会从系统目录开始搜索头文件。
- #include “filename”:用于包含用户自定义的头文件,这些头文件通常位于当前工程的源代码目录中。使用""来包含头文件,编译器会先从当前源文件所在目录开始搜索头文件,如果找不到,则继续在编译器的系统目录中搜索。
CPP的循环引用
使用#include时需要注意头文件的循环引用问题,如果存在循环引用,就需要使用前向声明(#pragma once或#ifndef等方式)或者重新设计头文件结构来避免循环引用。
import也是如此
总结
问题解决完成1