外部的神秘问题

时间:2011-04-25 14:11:23

标签: objective-c cocoa scope extern

在我的项目中,我 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来检查它们。所以从plist读取没有问题。

如果我使用第二部分,结果与预期一致,并且extern在任何地方都被识别。 :)

如果我正在使用第一部分,问题是我收到“EXC_BAD_ACCESS”:(无论我在哪里访问这些外部值,如果我将鼠标放在调试模式的变量上,我可以看到它打印“超出范围“但是外部变量在整个代码中都有范围。什么是神秘的。任何人???

2 个答案:

答案 0 :(得分:2)

如果你没有在垃圾收集下运行,那么第一部分代码需要保留这些字符串。否则,在分配它们后不久它们就会被解除分配,并且你将留下指向解除分配对象的指针。这是让EXC_BAD_ACCESS崩溃的好方法。

答案 1 :(得分:2)

虽然这些extern变量的确具有与程序相同的生命周期,但对于它们指向的对象并不一定如此:

kStrAgentStateLogin = @"ログイン";

rvalue是一个文字(或常量)NSString,它永远不会被运行时解除分配,所以你不必担心该字符串的内存管理。

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

rvalue是一个你不拥有的字符串(即你没有通过NARC方法获得它 - new,alloc,retain,copy),所以你不能指望它在程序执行过程中存在。您应该使用-retain拥有该字符串,确保它在整个程序中有效。