宏的使用:
它在项目中常见的使用方式有两种:
一,常用的字符串或者常量抽成宏
比如在项目该文件中多次使用到255这个常量
tableView.frame = CGRectMake(0, 0, 255, 360);
tableView.rowHeight = 255 / 5;
就可以把255抽成宏 #define AMTableHeight 255
tableView.frame = CGRectMake(0, 0, AMTableHeight, 360);
tableView.rowHeight = AMTableHeight / 5;
使用注意事项:使用宏时是要注意“边缘效应”。比如:
#define AMFontSize (4 + 3)一定要加括号,如果不加括号会出现问题。 因为在预编译的时候,(4 + 3)会替换项目中出现AMFontSize的地方,如果此时代码
button.titleLabel.font = [UIFont systemFontOfSize:AMFontSize * 2];
预编译之后代码变成了这样
button.titleLabel.font = [UIFont systemFontOfSize:(4 + 3) * 2];
运行时字号为14,结果正常。
如果不加括号,
button.titleLabel.font = [UIFont systemFontOfSize:4 + 3* 2];
字号就会变成10,结果异常。
二,常用的代码抽成宏
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(click) name:nil object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
这里就可以把 [NSNotificationCenter defaultCenter] 抽成
#define AMNotiCenter [NSNotificationCenter defaultCenter] 宏的形式,以上代码就可以写成以下形式
[AMNotiCenter addObserver:self selector:@selector(click) name:nil object:nil];
[AMNotiCenter removeObserver:self];
宏的命名规范:以项目前缀开头,以key结尾。#代表预编译
const的使用:
当有字符串常量或者基本常量的时候,苹果推荐我们使用const关键字。它的作用:
1,用来修饰右边的变量(只能修饰变量:基本变量,指针变量),const修饰的变量,表示只读。
CGFloat const value = 3;
NSString * const abc = @"123";
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%f",value);
NSLog(@"%@",abc);
}
打印结果为:
2017-08-28 16:04:55.554 02-const简单使用[8625:401018] 3.000000
2017-08-28 16:04:55.555 02-const简单使用[8625:401018] 123
打印结果正常,如果去修改变量的值,编译时就会报错,如下:
所以,可得出结论,const修饰的变量,变成了只读变量。
再看以下代码:
一:const修饰基本变量
- (void)viewDidLoad {
[super viewDidLoad];
// 用const修饰基本变量
// 方式一:
int const a = 10; // a:只读变量
// 方式二:
const int a = 10; // a:只读变量
//方式一和方式二 ,const修饰基本变量a效果是相同的。
}
二:const修饰指针变量
- (void)viewDidLoad {
[super viewDidLoad];
const int a = 10; // a:只读变量
const int b = 5;//只读变量
// 用const修饰指针变量
// int * const p = &a; // p:只读变量 *p:变量
// int const *p = &a; // *p:只读 p:变量
// int const * const p = &a; // *p:只读 p:只读
const int * const p = &a; // *p:只读 p:只读
NSLog(@"%d",*p);
}
为什么int const *p = &a这句代码,*p变为只读变量,而p未变。因为const关键字,它是修饰右边变量的,这句代码中 *p 位于右边,所以它是修饰*p的,而不是修饰p的。
在项目中const也是经常可以使用到的,它的应用场景有以下两种场景:
一,定义一个全局的只读变量。
NSString * const name = @"123";
二,在方法中定义只读参数
- (void)viewDidLoad {
[super viewDidLoad];
[self test:@"123"];
}
// 修饰对象
- (void)test:(NSString * const)name {
}
宏与const的区别
知道了两者的使用方法之后,就需要搞清楚他们之间的区别,方便在使用的时候,选择最优方案。
相同点:都具备抽取的功能,对于文件中多次出现的字符串常量或者基本类型的常量,二者都 可以抽取。(抽取的优点:便于修改,迭代)
不同点:1,编译时刻: 宏:预编译,const:编译。
2,编译检查: 宏:预处理时只是直接进行了替换,所以编译的时候不能进行数据类型检查。 const:在编译时进行严格的类型检验,可以避免出错。
比如:#define AMTableHeight 255adf& 这句代码明显有错,但是编译不报错
宏的优点:可以抽取代码。 宏的缺点:编译时间过长,因此常用的字符串通常使用const修饰
提示: 经常使用宏会造成内存不段增加,每次使用宏,都会分配一个内存,这个观点是错误的,只会分配一次内存。
static的使用
在项目中最常使用static的地方是:
一,修饰局部变量
作用:延长这个局部变量的生命周期,只要程序没有退出,局部变量就会一直存在。用static修饰的代码,在程序一启动就会执行,以后就不会再执行,变量只会分配一次内存。
二,修饰全局变量
作用: 修改全局变量的作用域,表示只能在当前文件内使用。
extern的使用
使用场景:一般用于声明全局变量
作用:声明一个变量,不能初始化。
例如:在 ViewController.m 文件中声明了一个全局变量
int a = 3;//全局变量a
想在AppDelegate.m文件中去使用 a 这个全局变量。extern就派上了用场。
在AppDelegate.m文件中,添加如下代码
extern int a;
此时在AppDelegate.m文件中就可以访问到a这个变量了。
static和const联合使用
项目中有这样的需求,把当前文件中多次使用到的字符串常亮、基本常亮抽取,而且要求作用域仅在当前文件中。static和const联合就能够很好的解决这个问题。
比如:要抽取@"123"字符串。
static NSString * const name = @"123";
分析代码:
1,static修饰全局变量,修改了作用域,表示在当前文件中使用
2,const修饰变量.变量只读,表示name的值不能被修改
结果name变量 在功能上就相当于是 当前文件中的常量。
extern和const联合使用
使用场景:在项目中用来修饰 全局只读变量 或者说 全局常量。
项目中往往会把多个文件用到的 全局常量 放在同一个文件中去管理,这样便于团队配合开发,减少冲突。
例如:一个项目中多个文件使用到了@"123"这个字符串。就会把@"123"字符串抽取到一个文件中,暂把这个文件取个Const名字。
在Const.h文件中,写法如下,声明一个name只读变量
UIKIT_EXTERN NSString * const name ;//UIKIT_EXTERN 就是 extern
在Const.m文件中,写法如下,声明name变量并赋值。
NSString * const name = @"123";
在需要使用字符串的文件中导入const.h即可。