Загадочная проблема с Экстерном - PullRequest
1 голос
/ 25 апреля 2011

В моем проекте у меня есть AuxState.h , где я определяю

extern NSString *kStrAgentStateLogin;
extern NSString *kStrAgentStateAvailable;
extern NSString *kStrAgentStateLogOff;
extern NSString *kStrAgentStateLunch;
extern NSString *kStrUnavailable_IDLE;

В AuxState.m У меня

NSString *kStrAgentStateLogin; 
NSString *kStrAgentStateAvailable;
NSString *kStrAgentStateLunch;
NSString *kStrAgentStateLogOff;
NSString *kStrUnavailable_IDLE;

В моем Appdelegate.m я импортировал AuxState.h и определил следующий метод, который устанавливает extern переменные

-(void) languageSetupForAuxStates
{

/* 1st Part */

kStrAgentStateLogin     =  @"Log In";
kStrAgentStateAvailable =  @"Available";
kStrAgentStateLunch     =  @"Lunch";
kStrAgentStateLogOff = @"Log Off";
kStrUnavailable_IDLE =  @"Unavailable/IDLE";

if([[[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0] isEqualToString:@"ja"]){

    kStrAgentStateLogin=[[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kAuxStatesDictFile ofType:@"plist"]] allKeysForObject:kStrAgentStateLogin] objectAtIndex:0];
    kStrAgentStateAvailable=[[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kAuxStatesDictFile ofType:@"plist"]] allKeysForObject:kStrAgentStateAvailable] objectAtIndex:0];


kStrAgentStateLunch=[[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kAuxStatesDictFile ofType:@"plist"]] allKeysForObject:kStrAgentStateLunch] objectAtIndex:0];

kStrUnavailable_IDLE=[[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kAuxStatesDictFile ofType:@"plist"]] allKeysForObject:kStrUnavailable_IDLE] objectAtIndex:0];
}

NSLog(@"kStrAgentStateLunch = %@",kStrAgentStateLunch);

/* 2nd Part */

if([[[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0] isEqualToString:@"ja"]){
    NSLog(@"Agent language is Japan");
    kStrAgentStateLogin         =  @"ログイン";
    kStrAgentStateAvailable     =  @"利用可能";
    kStrAgentStateLunch         =  @"昼食";
    kStrAgentStateLogOff            = @"ログオフ";
    kStrUnavailable_IDLE            =  @"できない/アイドル";
}
else {
    NSLog(@"Agent language is English");
    kStrAgentStateLogin         =  @"Log In";
    kStrAgentStateAvailable     =  @"Available";
    kStrAgentStateLunch         =  @"Lunch";
    kStrAgentStateLogOff            = @"Log Off";
    kStrUnavailable_IDLE            =  @"Unavailable/IDLE";
}

}

Теперь прочитанные значения одинаковы в обоих случаях.Я проверил их, выполнив также NSLog.Так что нет проблем при чтении из списка.

Если я использую 2-ю часть, результат будет таким, как ожидалось, и extern будет признан везде.:)

Если я использую 1-ю часть, проблема в том, что я получаю «EXC_BAD_ACCESS» :( везде, где я получаю доступ к этим внешним значениям, и если я помещаю свою мышь над переменными в режиме отладки, я вижу, что этовыводит «вне области видимости», но переменные Extern имеют область видимости во всем коде. В чем загадка? Кто-нибудь ???

Ответы [ 2 ]

2 голосов
/ 25 апреля 2011

Хотя эти extern переменные имеют то же время жизни, что и программа, это не обязательно относится к объектам, на которые они указывают:

kStrAgentStateLogin = @"ログイン";

Значение r является литералом (или константой) NSString, который никогда не освобождается средой выполнения, поэтому вам не нужно беспокоиться об управлении памятью этой строки.

kStrAgentStateLogin=[[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kAuxStatesDictFile ofType:@"plist"]] allKeysForObject:kStrAgentStateLogin] objectAtIndex:0];

Значение r - это строка, которой вы не владеете (т. е. вы не получили еес помощью метода NARC - new, alloc, retain, copy), поэтому вы не можете ожидать, что он будет существовать на протяжении всего выполнения вашей программы.Вы должны использовать -retain для владения этой строкой, чтобы быть уверенным, что она будет действительна во всей вашей программе.

2 голосов
/ 25 апреля 2011

Если вы не запускаете сборщик мусора, код 1-й части должен сохранить эти строки. В противном случае они могут быть освобождены вскоре после их назначения, и у вас останутся указатели на освобожденные объекты. Это отличный способ получить аварийное завершение EXC_BAD_ACCESS.

...