在我的iOS / Objective C项目中,我经常使用带有API密钥等的constants.h文件。直到今天,我一直宣称我的常量为static
const
,如此:
static NSString * const kAPIKey = @"wembvkejrvb43789gvbiu2bvfake";
这很好用,但有一个不幸的缺点,我可以只创建基元和NSString文字的常量。其他对象(如UIColor对象)不能存储在此常量中,因为它们无法使用静态文字语法进行初始化(我的理解,需要引用)。
在阅读了一些C ++文档后,我理解了一些事情:
static
是不必要的,因为const
是隐式静态的。NSString * const x
实际上是在x中声明一个常量且不可变的值。我无法更改值,但可以更改x指向的内容。这些结论是否正确?
extern const
有何不同?我假设它们是外部链接的(因此是extern关键字)。它们是在运行时定义的吗?我可以创建某种动态 extern const
,可以使用类方法返回的值进行设置吗?
例如,我想创建一个包含UIColor值的全局范围常量。我想使用[UIColor colorWithRed:green:blue:alpha:]
类方法构造此颜色值。这显然不适用于我一直在使用的内部链接常量(我假设因为它发生在编译时) - 但可能使用外部常量,可能在+initialize
方法中设置?
任何有关此行为细节的详细说明都会非常有用。
答案 0 :(得分:8)
静态是不必要的,因为const是隐式静态的。
不,那不是真的。
static
在文件范围内使用时(即在任何方法或函数之外)意味着该变量仅在该文件中可见。
extern
表示该变量在其他文件中定义。
const
表示无法修改变量。
考虑字符串。通常,您将有一个实现文件(名称以.m结尾)定义一些常量字符串指针:
NSString *const SomeString = @"some string";
您可能希望从其他文件中使用相同的常量。如果是这样,你可以在标题中添加一个声明(名称以.h结尾)文件,向编译器解释变量是在别处定义的:
extern NSString *const SomeString;
这将允许您在导入头文件的任何文件中使用SomeString
。另一方面,您可能会认为您确实不希望在实现文件外部使用常量。在这种情况下,您可以声明它static
(再次在实现文件中):
static NSString *const SomeString = @"some string";
这会阻止它在文件外使用。
调用
NSString * const x
实际上是在x中声明一个常量且不可变的值。我无法更改值,但可以更改x指向的内容。
是的,它声明指针x
是常量 - 你无法改变它。如果它实际上是NSString
,您也无法更改其指向的值,因为实例NSString
不可变。
此const具有内部链接,意味着该值立即定义(在编译时可以推测)。
我将在第5位 - 我不确定编译器如何处理常量字符串。不过,我认为将其用作心理模型是安全的。在任何情况下,字符串都会在您的代码使用之前定义。
答案 1 :(得分:1)
关于您的特定编程问题,如何创建编译时定义的颜色对象:您不能,因为除了少数语言提供文字语法之外,还会在运行时创建对象。
但是你仍然可以在运行时优雅地完成它,而不会增加全局范围,就像sdk所做的那样......
@interface UIColor (RainbowAddition)
+ (UIColor *)chartruseColor;
@end
@implementation UIColor (RainbowAddition)
+ (UIColor *)chartruseColor {
// bonus: this is really chartruse... according to the internet
return [self colorWithRed:0.5 green:1.0 blue:0.0 alpha:1.0];
}
@end
答案 2 :(得分:1)
Objective-C是C的纯粹扩展,C ++不是。
在全球范围内:
const
相当于extern const
(外部链接); const
等同于static const
(内部链接)。在C(和Objective-C)和C ++中,要创建一个全局范围的const
,您只需在extern const TYPE identifier = VALUE;
之类的源文件中定义它,并声明它(通常在头文件中):extern const TYPE identifier;
(读它:我在全局链接级别的其他地方定义了这个const)。