1. 宏的简单介绍
我在做项目时,发现很多开发者一般会创建一些名为Constant.h、Public.h的文件,在这些文件中定义大量的宏。有字符串常量、函数、方法等。
- 字符串常量,多是接口名、接口网址、在使用NSUserDefaults时的key等等,这样做的好处是,当接口网址或接口名变更时,我们只需要更改Constant文件中的宏,项目中对于这些字符串常量一次就能修改完,不会有所遗漏。
- 常用的函数、方法,比如修改颜色的方法
#define RGBA(r, g, b, a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
、屏幕尺寸#define screen_width [UIScreen mainScreen].bounds.size.width
等等。
2.PCH的简单介绍
PCH文件(Precompile Prefix Header File),也就是预编译头文件,其作用就是,方便你一次性导入在多个文件中同时用到的头文件、宏或者URL地址等(全局使用),可以有效的帮你节约时间,提高开发效率。我通常使用PCH引入常用的头文件,比如上面提到的Constant.h、Public.h,还有一些常用三方SDK头文件等等。关于PCH,我看到的下面这个网址的教程非常详细,在这里就不过多描述了。
3.const与宏的区别
const与宏的区别,从四个方面来记
- 编译时刻 宏:预编译; const:编译
- 编译检查 宏:没有编译检查; const:有编译检查
- 宏的好处 宏:可以定义函数、方法; const:不行
- 宏的坏处 宏:大量使用宏,会导致预编译时间过长
首先,解释下预编译,项目编译时,如下图所示,会有个蓝色的进度条,这就是在预编译。如果使用过多的宏,这个进度条就会异常缓慢。
编译检查,如下图所示,宏不会编译检查,而const会编译检查
很多Blog都说使用宏,会消耗很多内存 , 宏定义的是常量,常量都放在常量区,只会生成一份内存。我通过下面的代码验证并不会消耗很多内存。如下图所示,使用同一个宏,地址都是相同的。而且,定义完宏都是直接用的,我想没有人会先定义个变量,将宏赋值给变量,再去用变量吧,这样倒是会消耗许多内存……关于这里还有一点,我感觉那些Blog想表达的意思是,大量使用宏,会导致预编译时间过长……
4.const的使用
const的作用:
- 修饰const右边的基本变量(
int a
)或者指针变量(int *a
)- 被const修饰的变量是只读的
// const右边修饰的是str1,str1是只读的,但是*str1可以修改
NSString * const str1 = @"str1";
// const右边修饰的是*str2,*str2是只读的,但是str2可以修改
NSString const *str2 = @"str2";
const使用场景
- 修饰全局变量
- 修饰方法中的参数
苹果官方推荐用const定义全局变量,而不是使用宏。定义全局变量使用const的意义在于,定义一些key时(比如在NSUserDefaults中使用的key),我们不想让key随意修改(在存值时用的key,未取值时先修改了key,结果key取不到值)。
// 苹果官方不推荐使用宏
// #define nameKey @"nameKey"
// 推荐使用const,const修饰的nameKey是只读的,不能修改
NSString * const nameKey = @"nameKey";
- (void)test:(int const *)a
{
// 在方法中不想修改参数,添加const修饰符就无法修改了
*a = 1;
}
const与static联合使用
const用来修饰全局变量,使全局变量只读。 而static修饰全局变量,修改全局变量的作用域。我们定义一个全局变量来替代宏,但是我们希望这个全局变量仅仅作用在当前文件夹下,这时候就需要static来修饰了。
static NSString * const key = @"key";
const与extern联合使用
通常,我们需要将全局变量全部定义在同一个文件下使用,这样的好处在于方便管理,假如出现全局变量重名的情况,会直接报错,方便查找错误。
extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
// xx.h 文件中实现声明
extern NSString * const key;
// xx.m 文件中实现赋值
NSString * const key = @"lemontree";