最近在读一本effecttive Objective-C 2.0 ---- 编写高质量iOS与OS X代码的52个有效方法
笔者在这里记录一些比较好用的方法和技巧,如有错误或者疏漏,欢迎大家指正.
1. 编写代码时经常要定义常量, 例如, 要写一个UI视图类, 此视图显示出来之后就播放动画, 然后消失. 你可能想把播放动画的时间提取为常量.也许会用这种方法来做:
#define ANIMATION_DURATION 0.3;
上述的预处理指令会把源代码中的 ANIMATION_DURATION 字符串替换成0.3, 这确实可以实现,但是这样定义出来的变量没有类型信息. 动画的持续播放时间应该是NSTimeInterval类型, 此外预处理过程会把碰到所有的ANIMATION_DURATION一律换成0.3,假设此指令声明在,某个头文件中, 那么所有引入这个头文件的代码, 其ANIMATION_DURATION都会被替换成 0.3, 这很显然不够好,
2. 有个办法预处理指令来定义常量会更好:
static const NSTimeInterval kAnimationDuration = 0.3;
这种方式定义的常量包含了类型信息,清楚的描述了常量的含义.可知常量的类型, 如果定义很多常量的话,清晰明了不会觉得很乱.
还要注意命名规范:如果只是文件内使用,就在命名前面加上k; 若在类之外用, 就用类名作为前缀.
尽量不要在头文件(.h文件)中定义常量, 在实现文件(.m文件)中定义常量
变量一定要同时用static与const来声明. const修饰符不让其他人修改所声明的变量, 变量值改变的话编译器就会报错, static修饰符意味着该变量仅在此变量的编译单元(某个类的.m文件)可见, 作用域仅限于.m文件中, 假如声明变量时不加static的话, 编译器会为它创建一个"外部符号", 如果其他文件重名的话就会报错,
3. 全局变量:如果需要对外公开某个常量,比如通知中心注册对象name唯一且全局,这个字符串来可以声明一个外界课件的常值变量.此类常量需放在"全局符号表"global symbol table中, 以便可以在定义该常量的编译单元之外使用,定义与static const 不同:
// 在头文件 .h文件中
extern NSString *const = XYStringConstant;
// 在实现文件 .m文件中
NSString *const XYStringConstant = @"VALUE";
在常量的头文件中(.h文件)声明, 且在实现文件中(.m文件)定义.注意const修饰符的位置
extern 关键字:告诉编译器, 在全局符号表中有一个叫XYStringConstant的符号, 即编译器无须查看其定义, 允许代码使用此常量.
此类常量必须要定义, 而且只能定义一次(.m文件实现),实现文件生成目标文件时, 编译器会在"数据段"为字符串分配存储空间,链接器会把此目标文件与其他目标文件相链接生成最终的二进制文件.凡是用到该常量的时候, 链接器都将其解析.
#import <UIKit/UIKit.h> extern NSString *const XYLoginMangerDidLoginNotification; @interface XYViewController : UIViewController @end
#import "XYViewController.h" NSString *const XYLoginMangerDidLoginNotification = @"XYLoginMangerDidLoginNotification"; @implementation XYViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }
4. 总结:
1.不要用预处理指令定义常量,这样定义出来的常量不含类型信息,编译器只是会在编译前执行查找替换操作.即使有人重新定义了常量值,编译器也不会产生警告信息, 这将会导致程序中的常量值不一致.
2.在实现文件中使用static const定义"只在实现文件中可见的常量'由于此类常量不在全局符号表中, 所以无需为其名称加前缀.
3.在头文件中使用extern来声明全局变量, 并在相关实现文件中定义其值, 这种常量要出现在全局符号表中, 所以其名称应加以区隔, 通常用与之相关的类名做前缀