宏定义这个东东,估计大家在代码中应该天天用吧。
在我刚刚做的一个项目中,各种往代码里码“#define”这种预处理指令。
什么动画时长啊,cell高度啊,cell的个数啊,balabala,看得我这个心烦。
拿一个例子来讲:
A程序猿定义了一个UITableViewCell的高度为45。
#define HEIGHT_TABLEVIEWCELL 45;
B程序猿也定义了一个UITableViewCell的高度为50。
#define HEIGHT_TABLEVIEWCELL 50;
然后B在他写的.m文件中引用了A的文件,然后...然后...就没有然后了。
总结一句话就是,TMD,太乱了。
经过查找资料,发现确实有人提出过问题,并且提出了“少用#define”的建议。
(很明显没有多少人遵循这一建议,大家还在开心的#define)
提出这一观点的论据主要有以下两点:
(1) 就是像我刚才举的例子一样,如果B引用了A的文件,并且A、B两人的文件中的预定义指令的名字相同,那么就会产生冲突,结果就是A 中的预定义指令把B中的预定义指令代替了。
(2)没有类型定义,就像#define HEIGHT_TABLEVIEWCELL 45;这句代码中,我们只能从后边的45来推测是int类型或者float类型。但是具体 是哪一种,代码中并不能体现出来。
所以基于以上两点,我们应该尽量少的使用#define这种预定义指令。
那不使用#define,我们使啥捏?
这个问题问滴有水平!^^!
那就分为两种情况跟大家聊聊:
在Objective-C的语境下,“编译单元”一词通常指每个类的实现文件(以.m为后缀名)。
也就是说,我们只在当前这一个.m文件中使用。
这种情况我们就可以使用static和const来修饰变量,例如 static const NSString *kClassName = @"DemoClass";
参考以下代码:
// DemoViewController.h
#import <UIKit/UIKit.h>
@interface DemoViewController : UIViewController @end
// DemoViewController.m
#import "DemoViewController.h"
static const NSString *kClassName = @"DemoViewController"; @implementation DemoViewController @end
根据苹果官方代码我们可以发现,定义“编译单元”内的常量都是以"k",作为前缀。
若要在多个“编译单元”中使用,此类常量需放在“全局符号表”(global symbol table)中,以便可以在定义该常量的编译单元之外使用。
步骤稍微复杂一下,但是比把大象装冰箱要简单一点:
参考以下代码:
// DemoViewController.h
#import <Foundation/Foundation.h>
extern NSString *const DemoViewControllerClassName; @interface DemoViewController : UIViewController @end
// DemoViewController.m
#import "DemoViewController.h" NSString *const DemoViewControllerClassName =
@"DemoViewController"; @implementation DemoViewController @end
注意const关键字的位置。
为避免名称冲突,最好是用与之相关的类名做前缀。
系统框架中一般都这样做。例如UIKit就按照这种方式来声明用作通知名称的全局常量。
其中有类似UIApplicationDidEnterBackgroundNotification与UIApplicationWillEnterForegroundNotification这样的常量名。
总之,经过这个项目蛋疼的经历,大家还是在项目中尽量少的使用预定义指令。
另外附上咱家的微信公众号的二维码,没事儿可以扫扫哈。
有啥事儿大家可以随时留言交流。