文档章节

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

啊子同
 啊子同
发布于 2016/07/21 17:32
字数 1307
阅读 61
收藏 1

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

我们来看一段代码

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

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

用const来定义一个常量

const修饰符定义的变量是不可变的,比如说你需要定义一个动画时间的常量,你可以这么做:

static const NSTimeInterval kAnimateDuration = 0.3;

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

也许你已经发现了,如果你像这样定义:

static const NSString * kUserName = @"StrongX";

你是可以修改userName的值的,(说好的常量呢~~~)

首先我们需要确定的是以下两种写法是一样的:

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坑惨了——!)。

本文转载自:http://www.strongx.cn/?hmsr=toutiao.io&p=118&utm_medium=toutiao.io&utm_source=toutiao.io

共有 人打赏支持
啊子同
粉丝 0
博文 46
码字总数 10556
作品 0
广州
程序员
iOS开发,#define的使用(系列一)

1、判断当前设备是不是iOS7以上版本 #define IOSVERSION7ORABOVE (([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)? (YES):(NO)) 如果判断系统的设备在项目中使用频繁,那么...

召唤攻城狮
2014/04/10
0
0
iOS源码补完计划--AFNetworking 3.1.0源码研读

参拜一下AFNetworking的源码。 第四篇源码、暂时来看也是iOS方向的最后一篇、撸完准备趁着热乎撸一撸网络协议。 目录 准备工作 功能模块 AFURLSessionManager/AFHTTPSessionManager AFNetwo...

kirito_song
05/25
0
0
iOS深入学习:#define

ios#define 我建了一个iOS开发QQ交流群:714042473,大家可以一起来相互学习。 一般情况下,我们使用#define来定义一个常量,#define的本质是文本替换,例如#define INTPTR int*,这时候我们...

iOS洛柒
07/12
0
0
iOS深入学习:华丽的#define

我建了一个iOS开发QQ交流群:188647173,大家可以一起来相互学习。 还有一个群里面大神的个人站点www.mylonly.com,大家有不会的可以向他请教。 本片博客参考CocoaChina上面的文章,对内容进...

召唤攻城狮
2014/04/18
0
0
定制iOS 7中的导航栏和状态栏

由于种种原因,申请了一个开源中国的帐号,也许会由于我的不耐心,不会亲自去一步步的写博文,但准备把自己看到的好的,都转载过来,就当时资源的存储,也算是一种推广吧。 iOS 7 教程:定制...

谁家的阿毛
2013/11/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
11分钟前
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
45分钟前
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
0
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
2
0
设计模式之五 责任链模式(Chain of Responsibility)

一. 场景 相信我们都有过这样的经历; 我们去职能部门办理一个事情,先去了A部门,到了地方被告知这件事情由B部门处理; 当我们到了B部门的时候,又被告知这件事情已经移交给了C部门处理; ...

JackieRiver
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部