熟悉OC--4:多用类型常量,少用*define预处理指令

2023-11-22 08:17:29 浏览数 (1)

开发场景

编写代码经常需要定义常量,例如,写一个UI动画,需要定义一个动画播放时间,通常做法

代码语言:javascript复制
#define ANIMATION_DURATION 5

这行预处理指令会把源代码中的ANIMATION_DURATION替换为5,可以实现需求,但是这样写不太好,其原因:

  • 代码中并没有定义出常量的类型信息,duration表示时间,但是代码中,并没有表示出它值得类型
  • 预处理指令会把碰到的所有ANIMATION_DURATION全部替换为5

解决此问题,可以利用编译器的特性,代码如下

代码语言:javascript复制
static const NSTimeInterval kAnimationDuration = 5;

这样定义的好处

  • 清晰的描述了常量的含义,常量的类型
  • 命名习惯(若仅在该类.m文件中使用,则字母前加k,若在该类外也要使用,则加类名)

常量位置

  • 若不公开某个常量,则将其定义在该类的.m文件
代码语言:javascript复制
#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中定义
    • 这个常量名字,最好使用与之相关的类名做前缀
代码语言:javascript复制
#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

要点

  1. 不要用预处理指令定义常量,因为不含类型信息,而且有人改了常量值也不会报错
  2. 在实现文件里使用static、const来定义的常量只能在该类的.m文件中使用,此类常量不在全局符号中,所以无需加前缀
  3. 在头文件中使用extern来声明全局变量,并在相关实现文件中定义其值,这种常量要出现在全局符号表中,其名称需要加上与之相关的类名

参考

Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法

0 人点赞