谈谈为何iOS开发别用宏来定义常量_IOS

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

我们来看一段代码

#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指向的内存块地址,而他的输出是:


输出

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

而当我们的修饰符是这样的时候:

static NSString * const kUserName = @"StrongX";

我们则无法改变userName的值。

所以当我们需要定义一个不可变的常量的时候 ,我们还是需要将“const”修饰符放到“*”指针指向符后边才对。

一定要同时使用static和const来定义你的变量

上面已经说了const是用来定义一个常量。而static在C语言中(OC中延用)则表明此变量只在改变量的输出文件中可用(.m文件),如果你不加“static”符号,那么编译器就会对该变量创建一个“外部符号”,后果是什么呢?
你可以尝试在不同编译文件中加入以下代码:

NSString * const kUserName = @"StrongX";

可能尽管文件之间并没有相互引用,不存在属性名重复的问题(因为这并不是一个属性,这是一个外部符号),但是编译器还是报错了:

他会告诉你在两个目标文件(.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坑惨了!)。

以上就是本文的全部内容,希望本文提到的知识点对大家开发IOS时有所帮助,让大家都能使用正确的规范开发IOS。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios
, 常量
, 宏定义
定义常量
c 定义常量、java常量定义、php 定义常量、js定义常量、python 常量定义,以便于您获取更多的相关知识。

时间: 2024-11-05 16:35:38

谈谈为何iOS开发别用宏来定义常量_IOS的相关文章

iOS开发之自定义UITextField的方法_IOS

UITextField是IOS开发中用户交互中重要的一个控件,常被用来做账号密码框,输入信息框等. 观察效果图 UITextField有以下几种特点: 1.默认占位文字是灰色的 2.当光标点上去时,占位文字变为白色 3.光标是白色的 接下来我们通过不同的方法来解决问题 一.将xib中的UITextField与代码关联 通过NSAttributeString方法来更改占位文字的属性 (void)viewDidLoad { [super viewDidLoad]; // Do any additio

iOS开发 全机型适配解决方法_IOS

最近做项目,对于IPhone 手机机型适配很是头疼,所以整理下网上资料,记录下来,也许能帮助到正看文章的你, 今天打算跟大家聊聊最近研究的全机型适配思路. 当前我们需要适配的iPhone机型有4s.5s.6s.6Plus四种机型.它们的尺寸分别是  iphone4s {320, 480}                           960*640  iphone5 5s {320, 568}                       1136*640  iphone6 6s   {37

IOS 开发自定义条形ProgressView的实例_IOS

IOS 自定义进度条 ProgressView,好的进度条,让人赏心悦目,在等待的时候不是那么烦躁,也算是增加用户体验吧! 进度条在iOS开发中很常见的,我在项目开发中也写过好多进度条,有好多种类的,条形,圆形等,今天给大家总结一种条形的开发进度条. 简单思路:  1.自定义进度条先继承UIView 建立一个CustomBarProgressView  2.在.H文件中外漏的方法<开始的方法><初始化的方法>  3.在.M文件中 利用定时器改变位置 实现进度条 #效果图 #部分代码

iOS开发之事件传递响应链_IOS

当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了"单击"这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应.这一寻找的过程,被称作事件的响应链,如下图所示,不用的响应者以链式的方式寻找 事件响应链 一.响应者 在iOS中,能够响应事件的对象都是UIResponder的子类对象.UIResponder提供了

总结iOS开发中的断点续传与实践_IOS

前言 断点续传概述 断点续传就是从文件上次中断的地方开始重新下载或上传数据,而不是从文件开头.(本文的断点续传仅涉及下载,上传不在讨论之内)当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会去重头下载,这样很浪费时间.所以项目中要实现大文件下载,断点续传功能就必不可少了.当然,断点续传有一种特殊的情况,就是 iOS 应用被用户 kill 掉或者应用 crash,要实现应用重启之后的断点续传.这种特殊情况是本文要解决的问题. 断点续传原理 要实现断点续传 , 服

iOS开发————详解适配iOS10问题_IOS

2016年9月7日,苹果发布iOS 10.2016年9月14日,全新的操作系统iOS 10将正式上线. 作为开发者,如何适配iOS10呢? 1.Notification(通知) 自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大改重构,这让开发者也体会到UserNotifications的易用,功能也变得非常强大. •iOS 9 以前的通知 1.在调用方法时,有些方法让人很难区分,容易写错方法,这让开发者有时候很苦恼.

iOS开发系列--详细介绍数据存取_IOS

概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储,包括偏好设置其本质都是存储为文件,只是说归档或者plist文件存储可以选择保存到沙盒中,而偏好设置系统已经规定只能保存到沙盒的Library/Preferences目录.当然,文件存储并不作为本文的重点内容.本文重点还是说数据库存储,做过数据库开发的朋友应该知道,可以通过SQL直接访问数据库,也可以

iOS开发之路--微博骨架搭建_IOS

最终效果图: BeyondViewController.m // // BeyondViewController.m // 20_帅哥no微博 // // Created by beyond on 14-8-3. // Copyright (c) 2014年 com.beyond. All rights reserved. // 这个就是主控制器,分为两块,下面是Dock栏,上面是显示不同的子控制器的view,子控制器最好用导航控制器包装一下,这样子控制器就自带了导航条,左按钮,标题,右按钮 /

iOS开发之路--微博“更多”页面_IOS

最终效果图: MoreViewController.m // // MoreViewController.m // 20_帅哥no微博 // // Created by beyond on 14-8-4. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import "MoreViewController.h" @interface MoreViewController () { // more.plist根是字典