这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
开发场景
编写代码经常需要定义常量,例如,写一个UI动画,需要定义一个动画播放时间,通常做法
#define ANIMATION_DURATION 5
这行预处理指令会把源代码中的ANIMATION_DURATION替换为5,可以实现需求,但是这样写不太好,其原因:
- 代码中并没有定义出常量的类型信息,duration表示时间,但是代码中,并没有表示出它值得类型
- 预处理指令会把碰到的所有ANIMATION_DURATION全部替换为5
解决此问题,可以利用编译器的特性,代码如下
static const NSTimeInterval kAnimationDuration = 5;
这样定义的好处
- 清晰的描述了常量的含义,常量的类型
- 命名习惯(若仅在该类.m文件中使用,则字母前加k,若在该类外也要使用,则加类名)
常量位置
- 若不公开某个常量,则将其定义在该类的.m文件
#import "ViewController.h" static const NSTimeInterval kAnimationDuration = 5; @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self animation]; } - (void)animation{ [UIView animateWithDuration:kAnimationDuration animations:^{ }]; } @end
注意:
变量一定要同时用static
与const
来声明。
const
修饰符所声明的变量,如果修改就会报错
static
修饰符则意味着该变量仅在定义此变量的.m文件可见
- 对外公开某个常量(比如通知名称)
- 此类常量需要放在“全局符号表”中,这样别的类可以使用
- 这个常量在.h中声明,在.m中定义
- 这个常量名字,最好使用与之相关的类名做前缀
#import <UIKit/UIKit.h>
@interface LoginViewController : UIViewController
extern NSString *const LoginNoti;
@end
#import "LoginViewController.h"
NSString *const LoginNoti = @"login";
@implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]postNotificationName:LoginNoti object:nil];
}
@end
#import "ViewController.h"
#import "LoginViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(run) name:LoginNoti object:nil];
}
- (void)run{
NSLog(@"run");
}
@end
小结
- 不要用预处理指令定义常量,因为不含类型信息,而且有人改了常量值也不会报错
- 在实现文件里使用
static
、const
来定义的常量只能在该类的.m文件中使用,此类常量不在全局符号中,所以无需加前缀 - 在头文件中使用
extern
来声明全局变量,并在相关实现文件中定义其值,这种常量要出现在全局符号表中,其名称需要加上与之相关的类名