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

我正在创build一个用于学习目的的Reddit客户端。 我需要在其中有一个常量的文件。 我正在考虑导入Reddit-Prefix.pch文件中的文件,以使常量可用于所有文件。 这是做事的好方法吗? 另外,我已经完成了我的研究,发现了几个创build常量的方法,但是我不知道要使用哪一个:

  • #definemacros
  • const
  • static const
  • extern const
  • enum

那么首选的方式是哪一种? 什么是约定? 我知道“这取决于”,但更具体地说,我的问题是: 每种解决scheme的用例什么?

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

有一件事我可以从逻辑上得出结论,当定义像自定义错误域(我其实是对的?)时, enum是最好的select。 但是其他的呢?

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

  • 这些常量是特定于单个类的,还是将它们全部应用到应用程序中是有意义的?
  • 如果他们是特定类别的,他们是为了class级的客户,还是只在class级内使用?

如果它们对于一个类是特定的和内部的,那么将它们声明为.m文件顶部的static const ,如下所示:

 static NSString *const MyThingNotificationKey = @"MyThingNotificationKey"; 

如果它们属于一个类,但应该被其他类公开/使用,则在头文件中将它们声明为extern ,并在.m中定义它们:

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

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

你可以混合和匹配这些不同的常量,不同级别的你想让它们成为怎样的全局,也可以是不同的全局常量,这些常量根本不在一起 – 你可以把它们放在单独的模块中,每个模块都有自己的头文件想。

为什么不#define

旧的答案是“macros没有types信息”,但是今天的编译器对于所有types检查文字(macros扩展到什么)以及variables都非常聪明。

现代的答案是因为debugging器不会知道你的macros。 如果MyThingNotificationKey是macros,您不能在debugging器命令中说[myThing addObserver:self forKey:MyThingNotificationKey] ; debugging器只能知道它是否是一个variables。

为什么不enum

那么,rmaddy在评论中击败了我: enum只能定义整型常量。 诸如序列标识符号码,位掩码,四字节代码等

为了这些目的, enum是伟大的,你绝对应该使用它。 (更好的是,使用NS_ENUMNS_OPTIONSmacros 。)对于其他的事情,你必须使用别的东西; enum不做任何事情,但整数。

和其他问题

我正在考虑导入Reddit-Prefix.pch文件中的文件,以使常量可用于所有的文件。 这是做事的好方法吗?

可能无害,但可能过度。 在你需要的地方导入你的常量标题。

每个解决scheme有哪些用例?

  • #define :相当有限。 我真的不知道有一个很好的理由使用这个常量了。
  • const :最适合局部常量。 此外,你必须使用这个你在一个标题中声明,现在正在定义。
  • static const :最适合文件特定(或特定于类)的常量。
  • extern const :在一个头文件中导出一个常量时,你必须使用它。

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

您需要将文件导入到您使用它的每个文件或前缀标题中。

FOUNDATION_EXPORT

考虑使用FOUNDATION_EXPORTextern更具兼容性,因为它是在基础中定义的,并编译为C,C ++和Win32的兼容格式。

如NSObjCRuntime.h中所定义

 #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