我正在尝试确定这个问题是否有一个优雅的解决方案。
假设我在某个标题中定义了全局:
Constants.h:
extern NSString *someGlobal;
然后我希望在其他课程中使用这个全局:
Foo.m
NSString *localVariable = someGlobal;
如果我像这样初始化全局,这一切都可以正常工作:
Constants.m:
NSString *someGlobal = @"Some String Literal";
但是我要说我需要将全局初始化为不是编译时常量的东西。在这种情况下,我通常这样做:
Constants.m:
@implementation Constants
+ (void)initialize {
someGlobal = ... // some non-trivial initialization
}
@end
现在我在Foo.m
中遇到了潜在的问题。如果我尝试使用Constants
时未对someGlobal
课程进行过引用,则结果为nil
。解决方法是:
Foo.m(或在某些应用启动代码中):
[Constants class];
这将触发initialize
类的Constants
方法,someGlobal
将被正确初始化。只要在任何运行时使用someGlobal
之前完成此操作,就可以正常工作。
有没有更好的方法来初始化具有非编译时间常量的extern全局变量而无需在app启动时调用[Constants class
]之类的代码?
答案 0 :(得分:4)
Objective-C中更惯用的方法是使用单例而不是多个全局变量。方法如下:
@interface Globals
@property (readwrite,nonatomic) NSString *myString;
@property (readwrite,nonatomic) int myInt;
+(Globals*) instance;
@end
+(Globals*) instance {
static dispatch_once_t once;
static Globals *inst;
dispatch_once(&once, ^{
inst = [[Globals alloc] init];
inst.myString = @"Some String Literal";
inst.myInt = 42;
});
return inst;
}
现在你可以像这样使用你的全局:
NSLog(@"Global string: %@", [Globals instance].myString);
NSLog(@"Global string: %d", [Globals instance].myInt);
答案 1 :(得分:3)
不,没有更好的方法。从逻辑上讲,如果在变量初始化之前必须执行某些代码,则必须采取措施以确保发生这种情况。
您可以安排程序代码的流程,以保证Constants
类在执行任何其他需要它的代码之前得到初始化。例如,通过调整程序中初始化事物的顺序并遵循从main()
开始执行代码的顺序来向自己证明它是有效的。但缺少这一点(在任何情况下都是最安全的),你会使用你的技术强制它在你使用之前变得有效。
答案 2 :(得分:1)
就像dasblinkenlight的回答一样,这可能不是您正在寻找的,但这是另一种方法。
我会使类方法返回您正在寻找的值,如下所示:
+(NSString *)someConstant {
static NSString *constant;
if(constant == nil)
constant = //your initialization here;
return constant;
}
然后您需要使用它,只需致电[Constants someConstant];
其他随意的想法: 一个不是某个编译时间值的常量并不是真正的外部变量,这个方法确保每次使用它时都会初始化变量。使用常量的类无论如何都必须知道你的类,否则它不会导入它的头文件