美文网首页
iOS 少用#define预处理指令,多用类型常量

iOS 少用#define预处理指令,多用类型常量

作者: Yimmm | 来源:发表于2021-02-25 15:15 被阅读0次
    • 少用#define预处理指令,多用类型常量

    在写代码时尽量不要用预处理指令(#define)来定义常量,因为这样定义出来的常量不包含类型信息。

    如:

    #define ANIMATION_DURATION 0.3 // 定义一个动画播放时间
    

    编译器在编译前根据此执行查找与替换操作。即使在后面重新定义了常量值,编译器也不会产生警告,这可能会导致在应用程序中运行时获取的常量值不一致。
    因为Objective-C没有“命名空间”这一概念,这样就有互相冲突的可能了,如果在头文件声明了预处理指令,那么所有引入了所有这份头文件的其他文件里都会出现这个名字。

    为了解决这个问题,如果不打算公开某个预处理指令常量,将其常量定义在实现文件( .m)里,利用编译器的特性:

    // 如果视图修改const修饰的变量,编译器就会报错。
    // static意味着该变量尽在定义此变量的编译单元(通常指每个类的实现文件)中可见。
    static const NSTimeInterval kAnimationDuration = 0.3;
    

    如果不加static,另一个编译单元也声明了同名变量的话,编译器会抛出一条错误信息。

    duplicate symbol _kAnimationDuration in:
            EOCAnimatedView.o
            EOCOtherView.o
    

    这样更清晰地描述了常量的含义和类型,有利于编写开发文档,在定义了大量常量后,这种方式能令稍后阅读代码的人更容易理解其意图。

    有时候如果需要对外公开某个常量,比如在使用调用NSNotificationCenter来通知他人的时候。派发通知时,需要使用字符串来表示通知名称,这个名字可以声明一个为外界可见的常值变量,此类变量需放在“全局符号表”中,以便定义该变量的编译单元之外使用。

    // .h
    // 编译器看到extern关键字,默认全局符号表中将有一个EOCStringConstant的符号
    // 编译器知道,当链接成二进制文件后,就能找到这个常量
    extern NSString *const EOCStringConstant;
    
    // .m
    // 一个指针常量,指向NSString对象
    NSString *const EOCStringConstant = @"VALUE";
    

    此类常量必须定义且只能定义一次。实现文件生成目标文件时,编译器会在“数据段”(data section)为字符串分配存储空间。凡使用到 EOCStringConstant 这个全局符号的地方,里,链接器就能将其解析。
    因此,命名常量时需谨慎,最好用与之相关的类名做前缀,系统框架一般都会这样做。
    例如UIKit中,有UIApplicationDidEnterBackgroundNotification这样的常量名。
    假如要将EOCAnimatedView类的动画播放时长对外公布,可以这样声明:

    // EOCAnimatedView.h
    extern const EOCAnimatedViewAnimationDuration;
    
    // EOCAnimatedView.m
    const NSTimeInterval  EOCAnimatedViewAnimationDuration = 0.3;
    

    这样定义,编译器能保证常量值不变,亦可随处使用。

    -2021.02.25

    相关文章

      网友评论

          本文标题:iOS 少用#define预处理指令,多用类型常量

          本文链接:https://www.haomeiwen.com/subject/gsvyfltx.html