参考文档
1. 为什么少用 #define?
#define avatar @"60"
if (false) {
#define avatar @"80"
}
NSLog(avatar); //结果是80
如上代码中,avatar 定义为60,然后在一个永不执行的if代码中定义为80。
但编译时期,编译器会编译这段代码,而这个时候编译器会将 avatar 替换成80。
2. 用 const 来定义常量
const修饰符定义的变量是不可变的,比如定义一个动画时间的常量:
static const NSTImeInterval kAnimateDuration = 0.3;
当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。
更加重要的是用这种方法定义的常量是带有类型信息的,
而这点则是define不具备的。
注意:
这两种写法是没有差别的
static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";
const 修饰右边的部分
static NSString const * kUserName = static NSString const (* kUserName )
static NSString * const kUserName = static NSString * const (kUserName)
当const 修饰 userName 时,不可变的是 userName;
而*表示指针指向符,即这时候 userName 指向的内存块地址不可变,而内存保存的内容是可变的。
NSLog(@"内存地址: %x",& kUserName);
kUserName = @"superXLX";
NSLog(@"内存地址: %x",& kUserName);
//内存地址不变,但内容改变
修饰不可变的常量时,需要将 const 修饰放到星号指针指向符后边
3. 一定要同时使用static和const来定义你的变量
const是用来定义一个常量,static在C语言中(OC中延用)则表明此变量只在改变量的输出文件中可用(.m文件)。
如果你不加“static”符号,那么编译器就会对该变量创建一个“外部符号”。如果在不同编译文件中加入以下代码:
NSString * const kUserName = @"StrongX";
可能虽然文件之间并没有相互引用,不存在属性名重复的问题(因为这并不是一个属性,这是一个外部符号),但是编译器还是报错。
他会告诉你在两个目标文件(.0文件是.m文件编译后的输出文件)有一个重复的符号。(OC中没有类似C++中的名字空间的概念)
所以当你在你自己的.m文件中需要声明一个只有你自己可见的局部变量(k开头)的变量的时候一定要同时使用“static”和“const”两个符号
4. 工程中的全局变量
在我们的工程中一定会定义很多全局常量,一般在某个文件中用#define声明许多常量,然后将这个头文件引入“pch”文件中。
不能说这么做不对,但是如同上面说的那样define可能被修改,当然在命名规范的情况下这种情况很少出现,并且这样做的效率很高。
但苹果更推荐另外一种做法:”extern”,这样做的优势是保持常量绝对不会被修改,并且一定初始化还带有类型信息。
在“constants.h”文件中,声明常量
extern NSString *const XUserName;
然后在“constants.m”中定义常量
NSString *const XUserName = @"StrongX";
用“extern”定义的常量必须也只能初始化一次,不满足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名。
5. 汇总示例
- 项目中如果需要私有的常量,正常在.m文件中声明
而不建议用 #define
/// 显示远程推送内容
static NSString * const ShowRemoteNotificationContentKey = @"ShowRemoteNotificationContentKey";
/// 刷新裸车毛利数据
static NSString * const RefreshDealerGrossProfitNotificationKey = @"RefreshDealerGrossProfitNotificationKey";
/// 需要重新登录
static NSString * const ReLoginNotificationKey = @"ReLoginNotificationKey";
/// 刷新竞品价格数据
static NSString * const RefreshCompetitivePricesNotificationKey = @"RefreshCompetitivePricesNotificationKey";
- 正常公开的字符串常量定义方式是使用extern关键字
在.h 文件中定义
/// 用户Token Key
extern NSString * const QXUserTokenKey;
/// 用户UUID
extern NSString * const QXUserUUIDKey;
/// 用户所在的城市
extern NSString * const QXUserCityKey;
/// 第一次启动应用
extern NSString * const QXFirstLaunchKey;
在.m 文件中
/// 用户Token Key
NSString * const QXUserTokenKey = @"com.qianxx.user.token";
/// 用户UUID
NSString * const QXUserUUIDKey = @"com.qianxx.user.uuid";
/// 用户所在的城市
NSString * const QXUserCityKey = @"com.qianxx.user.city";
/// 第一次启动应用
NSString * const QXFirstLaunchKey = @"com.qianxx.user.isFirstLaunch";