在Objective-C中创build常量的最佳方法是什么?
我正在创build一个用于学习目的的Reddit客户端。 我需要在其中有一个常量的文件。 我正在考虑导入Reddit-Prefix.pch
文件中的文件,以使常量可用于所有文件。 这是做事的好方法吗? 另外,我已经完成了我的研究,发现了几个创build常量的方法,但是我不知道要使用哪一个:
-
#define
macros -
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_ENUM
和NS_OPTIONS
macros 。)对于其他的事情,你必须使用别的东西; enum
不做任何事情,但整数。
和其他问题
我正在考虑导入Reddit-Prefix.pch文件中的文件,以使常量可用于所有的文件。 这是做事的好方法吗?
可能无害,但可能过度。 在你需要的地方导入你的常量标题。
每个解决scheme有哪些用例?
-
#define
:相当有限。 我真的不知道有一个很好的理由使用这个常量了。 -
const
:最适合局部常量。 此外,你必须使用这个你在一个标题中声明,现在正在定义。 -
static const
:最适合文件特定(或特定于类)的常量。 -
extern const
:在一个头文件中导出一个常量时,你必须使用它。
另外,如果使用
extern const
,我是否需要导入文件,或者常量将在全局可用而不导入文件?
您需要将文件导入到您使用它的每个文件或前缀标题中。
FOUNDATION_EXPORT
考虑使用FOUNDATION_EXPORT
比extern
更具兼容性,因为它是在基础中定义的,并编译为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