iOS 不要用宏来定义你的常量

首先,预处理命令他不是一个常量!!!!

咱们来看一段代码动画

#define avatar @"60"
if (false) {
#define avatar @"80"
}
NSLog(avatar);

这段代码会输出多少,咱们将“avatar”定义为了60,而后在一个永远不会执行的代码里面从新定义了“avatar”为80,if语句中的代码 永远不会执行,可是在编译时期,编译器会编译这段代码,而这个时候编译器就会将avatar这个名字替换为@“80”,因此这段代码最后的输出结果就是 80。
固然这个时候编译器是会有一个警告的,可是不知道有多少同窗会忽略这个警告。或者你会告诉我你对警告十分敏感,不会放过他的,可是记住你不是一我的在写代码,可能在别人的页面他给你从新定义了你的define,给你挖了一个大坑,还找不着………spa

用const来定义一个常量

const修饰符定义的变量是不可变的,好比说你须要定义一个动画时间的常量,你能够这么作:指针

static const NSTimeInterval kAnimateDuration = 0.3;

当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。更加剧要的是用这种方法定义的常量是带有类型信息的,而这点则是define不具有的。code

也许你已经发现了,若是你像这样定义:内存

static const NSString * kUserName = @"StrongX";

你是能够修改userName的值的,(说好的常量呢~~~)编译器

首先咱们须要肯定的是如下两种写法是同样的:io

static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";

也就是说const放在类型前仍是类型后是同样的效果。而后不一样效果的是下面这种写法:编译

static NSString * const kUserName = @"StrongX";

const 修饰的是他右边的部分,也就是说:效率

static NSString const * kUserName = static NSString const (* kUserName )

static NSString * const kUserName = static NSString * const (kUserName)

当const修饰的是(userName)的时候,不可变的是userName;星号在C语言中表示
指针指向符,也就是说这个时候
userName指向的内存块地址不可变,而内存保存的内容是可变的,咱们来作个尝试:变量

NSLog(@"内存地址: %x",& kUserName);
kUserName = @"superXLX";
NSLog(@"内存地址: %x",& kUserName);

以上NSLog会打印*userName指向的内存块地址,而他的输出是:
DF448813-C948-4A8B-A545-7BE2A86EBD08

咱们已经发现当咱们改变内存的内存的时候他的地址并无发生改变,也就是说这是符合“const”修饰符的规定的。
而当咱们的修饰符是这样的时候:

static NSString * const kUserName = @"StrongX";

咱们则没法改变userName的值。

因此当咱们须要定义一个不可变的常量的时候 ,咱们仍是须要将“const”修饰符放到“*”指针指向符后边才对。

  • ### 必定要同时使用static和const来定义你的变量
    上面已经说了const是用来定义一个常量。而static在C语言中(OC中延用)则代表此变量只在改变量的输出文件中可用(.m文件),若是你不加“static”符号,那么编译器就会对该变量建立一个“外部符号”,后果是什么呢?
    你能够尝试在不一样编译文件中加入如下代码:
NSString * const kUserName = @"StrongX";

可能尽管文件之间并无相互引用,不存在属性名重复的问题(由于这并非一个属性,这是一个外部符号),可是编译器仍是报错了:

C7F125B8-CADA-435A-8A02-2CB9011F8D9F
他会告诉你在两个目标文件(.0文件是.m文件编译后的输出文件)有一个重复的符号。(OC中没有相似C++中的名字空间的概念)
因此当你在你本身的.m文件中须要声明一个只有你本身可见的局部变量(k开头)的变量的时候必定要同时使用“static”和“const”两个符号。

定义工程中的全局变量

在咱们的工程中必定会定义不少全局常量,不少人的作法是会建立一个“ constant.h”文件,在这个文件中用#define声明许多常量,而后将这个头文件引入“pch”文件中,不能说这么作不对,可是如同上面说的那 样define可能被修改,固然在命名规范的状况下这种状况不多出现,而且这样作的效率很高。
然而苹果更推荐另一种作法:”extern”,这样作的优点是保持常量绝对不会被修改,而且必定初始化还带有类型信息。
咱们在”constants.h”文件中,声明常量:

extern NSString *const XUserName;

而后在“constants.m”中定义他:

NSString *const XUserName = @"StrongX";

用“extern”定义的常量必须也只能初始化一次,不知足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候须要要注意你的命名,你可使用规定好的前缀来命名。

“define”和“extern”各有各的优点,不过我我的仍是比较推荐使用“extern”.(由于以前在一个工程中被define坑惨了——!)。

相关文章
相关标签/搜索