2013-02-23 2 views
0

Я пытаюсь определить, есть ли элегантное решение этой проблемы.Использование «extern» global перед правильной инициализацией

Скажем, у меня есть глобальная, определенная в некоторой заголовок:

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, все будет работать нормально.

Есть ли лучший способ инициализировать внешние глобальные переменные с некомпилируемыми константами времени без необходимости вызова кода, такого как [Constants class] при запуске приложения?

ответ

3

Нет, нет лучшего способа. Логически, если какой-то фрагмент кода должен выполняться до того, как переменная будет выполнена, вам необходимо предпринять шаги, чтобы убедиться, что это происходит.

Вы можете упорядочить поток кода своей программы, чтобы гарантировать, что класс Constants инициализируется, прежде чем любой другой кусок кода будет им нужен. Например, путем настройки порядка, в котором вещи инициализируются в вашей программе, и следуя порядку выполнения кода от main() вниз, чтобы доказать, что он работает. Но, кроме этого (и в самом безопасном случае в любом случае), вы использовали бы свою технику, чтобы заставить ее быть действительной прямо перед ее использованием.

+0

Спасибо. Это мой нынешний подход. – rmaddy

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); 
+0

Я согласен, что это лучший способ сделать это, если вы готовы отказаться от «простой» переменной C. – Celada

+0

В некоторых случаях это жизнеспособный подход, но я надеялся на более общее решение. Реальность заключается в том, что у меня есть проект с 100 классами, а несколько классов определяют внешние глобальные переменные. Было бы нецелесообразно собирать глобалы из рассеянных классов в один синглтон или определять целую кучу синглетов, чтобы справиться с несколькими нетривальными константами. Но это хорошо иметь в виду. Благодарю. – rmaddy

1

Как ответ dasblinkenlight, это может быть не совсем то, что вы ищете, но это другой подход.

Я бы методы класса, который возвращает значение, которое вы ищете, как это:

+(NSString *)someConstant { 
    static NSString *constant; 
    if(constant == nil) 
     constant = //your initialization here; 
    return constant; 
} 

Затем, когда вам нужно использовать его просто называют [Constants someConstant];

Другие случайные мысли: Константа это не какое-то значение времени компиляции, на самом деле это не те внешние переменные, и этот метод гарантирует, что переменная инициализируется каждый раз, когда вы ее используете. Класс, использующий константу, должен знать о вашем классе в любом случае или не импортировал бы его заголовочный файл

Смежные вопросы