使用" extern"正确初始化之前的全局

时间:2013-02-23 01:22:34

标签: objective-c

我正在尝试确定这个问题是否有一个优雅的解决方案。

假设我在某个标题中定义了全局:

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]之类的代码?

3 个答案:

答案 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];

其他随意的想法: 一个不是某个编译时间值的常量并不是真正的外部变量,这个方法确保每次使用它时都会初始化变量。使用常量的类无论如何都必须知道你的类,否则它不会导入它的头文件