在Objective-C中创建常量的最佳方法是什么

What is the best way to create constants in Objective-C

我正在创建一个Reddit客户机,用于学习目的。我需要一个包含常量的文件。我正在考虑导入Reddit-Prefix.pch文件中的文件,以使常量可用于所有文件。这是做事情的好方法吗?此外,我做了研究,发现了几种创建常量的方法,但我不知道该使用哪种方法:

  • #define
  • const
  • static const
  • extern const
  • enum

那么首选哪种方式呢?什么是惯例?我知道"它取决于",但我的问题更具体地说是:每个解决方案的用例是什么?

另外,如果使用extern const,是否需要导入文件,或者常量将在不导入文件的情况下全局可用?

从逻辑上讲,我可以得出一个结论:当定义自定义错误域时,enum是最佳选择(我真的正确吗?)其他人呢?


第一个问题是您希望常量具有什么范围,这实际上是两个问题:

  • 这些常量是特定于单个类的,还是在整个应用程序中都使用它们有意义?
  • 如果它们是特定于类的,它们是供类的客户机使用,还是只在类内使用?

如果它们是特定的且属于单个类,则在.m文件的顶部将它们声明为static const,如下所示:

1
static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

如果它们属于单个类,但应该是公共的/由其他类使用,则在头中声明它们为extern,并在.m中定义它们:

1
2
3
4
5
//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

如果它们应该是全局的,则在头中声明它们,并在相应的模块中定义它们,特别是那些常量。

您可以将它们混合并匹配到具有不同全局性级别的不同常量中,对于完全不属于一起的不同全局常量,您可以将它们放在单独的模块中,每个模块都有自己的头(如果需要)。

为什么不是#define

旧的答案是"宏没有类型信息",但是现在的编译器非常聪明,可以对文本(宏扩展到什么)和变量进行所有类型检查。

现代的答案是因为调试器不知道您的宏。如果MyThingNotificationKey是一个宏,在调试器命令中不能说[myThing addObserver:self forKey:MyThingNotificationKey];调试器只能知道它是一个变量。

为什么不是enum

嗯,rmaddy在注释中击败了我:enum只能定义整数常量。例如序列标识符编号、位掩码、四字节代码等。

为了达到这个目的,enum非常好,你绝对应该使用它。(更好的是,使用NS_ENUMNS_OPTIONS宏。)对于其他东西,必须使用其他东西;enum只做整数。

还有其他问题

I was thinking about importing the file in the Reddit-Prefix.pch file to make the constants available to all the files. Is it a good way of doing things?

可能无害,但可能过量。在需要的地方导入常量头。

What are the use cases for each of those solutions?

  • #define:相当有限。老实说,我不确定是否有足够的理由再把它用于常量。
  • const:最适合本地常量。另外,您必须对您在头中声明并且现在正在定义的那个使用这个。
  • static const:最适合文件特定(或类特定)常量。
  • extern const:导出头中的常量时必须使用该参数。

Also, if using extern const, do I need to import the file, or the constants will be available globally without importing the file?

您需要导入文件,无论是在使用它的每个文件中还是在前缀头中。


基金会出口

考虑使用EDCOX1,15,比EDCOX1,1的兼容性多一点,因为它是在基础上定义的,并编译成C、C++和Win32的兼容格式。

如nsobjcruntime.h中的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern"C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif