Effective OC 笔记 4多用类型常量,少用#define预处理指令
来源:互联网 发布:高维稀疏数据 编辑:程序博客网 时间:2024/06/07 22:10
1 定义常量
编写代码经常会用到常量,如:
#define AB_LANGUAGE_ZH 1#define AB_LANGUAGE_EN 2#define AB_LANGUAGE_AR 3#define AB_LANGUAGE_DE 4这是之前我们代码中定义的常量,只从名字根本不值得这是什么类型的数据,只知道大概和语言有关系。
又如:将ui视图中播放动画的时间提取为常量,我们经常会这样做(这样定义的很方便):
#define ANIMATION_DURATION 0.5该预处理指令会把代码中所有ANIMATION_DURATION替换为0.5。这可能是我们想要的效果,不过这样定义的常量没有类型信息。假设此指令声明在某个头文件中,那么所有引入了这个头文件的代码,其ANIMATION_DURATION都会被替换。
解决方法:
static const NSTimeInterval kAnimationDuration 0.5此方式定义的常量包含类型信息,很清楚的描述了常量的含义。
还要注意常量名称。常用的命名法是:
若常量局限于“编译单元”(也即是“实现文件”)之内,则在前面加字母k;
若常量在类之外可见,则通常以类名为前缀。
定义位置
定义常量的位置很重要。我们总是喜欢在头文件里声明预处理指令,这样做真的很糟糕,当常量名称有可能互相冲突时更是如此。
例如,ANIMATION_DURATION这个常量名就不该用在头文件中,因为所有引入了这份头文件的其他文件中都会出现这个名字。其实就连用satic const定义的变量也不应在头文件中,如果这样就等于声明了一个叫kAnimationDuration的全局变量。
2 不公开常量
若不打算公开某常量,则应将其定义在使用该常量的实现文件里。例如:
//// EOCAnimatedView.h//#import <UIKit/UIKit.h>@interface EOCAnimatedView : UIView@end//// EOCAnimatedView.m//#import "EOCAnimatedView.h"static const NSTimeInterval kAnimataionDuataion = 0.5;@implementation EOCAnimatedView@end
常量要同时用static与const来声明。如果试图修改由const声明的变量,那么编译器就会报错。
而static修饰符则意味着该变量仅在定义此变量的编译单元(在OC环境下,“编译单元”通常指某个类的实现文件)中可见。编译器没收到一个编译单元,就会输出一份“目标文件”,因此kAnimationDuration变量,其作用域仅限于由EOCAnimatedVIew所生成的目标文件。假如声明此变量不加static,编译器会为它创建一个“外部符号”。此时若另一个编译单元也声明了同名变量,那么编译器会抛错误:
duplicate symbol _kAnimationDuration in: EOCAnimatedView.o EOCOtherView.o如果一个变量既声明为static,也声明为const,那么编译器根本不会创建符号,而是像#define预处理指令一样,把所有kAnimationDuration 都替换为常值。
3 公开常量
如果打算公开某个常量。如:在类代码中调用NSNotificationCenter通知其他类,用一个对象来派发通知,。派发通知时,需要使用字符串来表示此项通知的名称,这个名字就可以声明为一个外界可见的常值变量。这样,注册者无须知道实际字符串值,只需以常值变量来注册资金想要接收的通知即可。
定义:
//In the header file extern NSString *const EOCStringConstant;//In the implementation fileNSString *const EOCStringConstant = @"VALUE";注意const修饰符在常量类型中的位置。常量定义应从右至左解读。EOCStringConstant就是“一个常量,而这个常量是指针,指向NSString对象”。
编译器看到头文件中的extern关键字,就能明白如何在引入头文件的代码中处理该常量了。这个关键字是要告诉编译器,在全局符符号表中将会有一个名叫EOCStringConstant的符号。也就是会所,编译器无须查看其定义,即允许代码使用此常量。因为它知道,当链接成二进制文件后,肯定能找到这个常量。
因为符号要放在全局符号表中,所以命名时需谨慎。为避免名称冲突,最好用与之相关的类名做前缀。系统框架一般都这样做。如:UIKit中,
UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification。
4 要点
1 不要用预处理指令定义常量。这样定义出来的常量不含类型信息,编译器只是会在编译前据此执行查找与替换操作。即使有人重现定义了常量值,编译器也不会产生警告⚠️,这将导致应用程序中的常量值不一致。
2 在实现文件中使用static const来定义“只在编译单元内可见的常量”。由于此类常量不在全局符号表中,所以无须为其名称加前缀。
3 在头文件中使用extern来声明全局常量,并在相关实现文件中定义其值。这种常量要出现在全局符号表中,所以其名称应加以区隔,通常用与之相关的类名做前缀。
- Effective OC 笔记 4多用类型常量,少用#define预处理指令
- Effective Objective-C 2.0 第4条:多用类型常量,少用#define预处理指令
- 多用类型常量,少用#define预处理指令
- 多用类型常量,少用#define预处理指令
- 多用类型常量,少用#define预处理指令
- IOS 多用类型常量,少用#define预处理指令
- iOS Objecttive-C语言 定义常量的几种方式与区别 static const 定义常量 少用#define预处理指令 多用类型常量
- iOS 高级开发技巧 1.熟悉Objective-C (四) 多用类型常量 少用#define预处理命令
- IOS 开发笔记——使用类型常量,少用预处理命令
- Effective OC 笔记 3多用字面量语法
- 尽量用类型化的常量替代预处理器的 #DEFINE 方法
- 尽量用类型化的常量替代预处理器的 #DEFINE 方法
- 预处理指令define
- 预处理指令(2) - #define
- 预处理指令--define
- 多用GCD,少用PerformSelector
- 多用GCD,少用performSelector
- 多用GCD,少用performSelector
- AJAX请求传JSON数据
- 架构笔记
- SpringMVC web.xml配置
- 关于UIButton的图文混排之图片
- POI导出文件报错 java.lang.RuntimeException: java.io.IOException: 系统找不到指定的路径。
- Effective OC 笔记 4多用类型常量,少用#define预处理指令
- Ubuntu下使用Python3
- PHP获取数组的键与值
- 现代嵌入式计算 - 第16章 - 设计实例 (第2部分)
- 小米手机市场份额为何下降
- 基本该公司的人员来源大部分来自应届生
- 如何花一分钟时间屏蔽网站广告(超实用)
- [LeetCode]383. Ransom Note
- android所读的书籍