Objective-C静态字段问题

时间:2011-07-13 02:36:16

标签: iphone objective-c ios

我创建了一个从plist文件加载字典项的小类。 getSettingForKey方法在我第一次调用静态方法时工作,但是在多次调用之后,字典会为具有在先前调用上工作的相同键的调用抛出SIGABRT异常。有什么想法吗?

static NSDictionary *dictionary = nil;
static NSLock *dictionaryLock;

@implementation ApplicationSettingsHelper

+ (void) initialize
{
    dictionaryLock = [[NSLock alloc] init];

    // Read plist from application bundle.
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSString *finalPath = [path stringByAppendingPathComponent:@"Xxxx.plist"];
    dictionary = [NSDictionary dictionaryWithContentsOfFile:finalPath];

    // dump the contents of the dictionary to the console.
    for(id key in dictionary)
    {
        NSLog(@"bundle: key=%@, value=%@", key, [dictionary objectForKey:key]);
    }
}

+ (NSDictionary *)dictionaryItems 
{
    [dictionaryLock lock];

    if (dictionary == nil)
    {
        [self initialize];
    }

    [dictionaryLock unlock];

    return dictionary;
}

+(id)getSettingForKey:(NSString *)key
{        
    return [[self dictionaryItems] objectForKey:key];
}

@end

Moshe - 我已采纳您的建议并更新为使用NSUserDefaults:

+ (void)load 
{   
    // Load the default values for the user defaults    
    NSString* pathToUserDefaultsValues = [[NSBundle mainBundle]
                                          pathForResource:@"Xxxx" 
                                          ofType:@"plist"];

    NSDictionary* userDefaultsValues = [NSDictionary dictionaryWithContentsOfFile:pathToUserDefaultsValues];

    // Set them in the standard user defaults
    [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValues];
}

+ (id)getSettingForKey:(NSString *)key
{        
    return [[NSUserDefaults standardUserDefaults] valueForKey:key];
}

2 个答案:

答案 0 :(得分:8)

您的字典可能已被取消分配,导致无效的内存访问。使用dictionaryWithContentsOfFile:方法创建字典时,它是自动释放的,这意味着它将来会自动释放。由于您从不保留字典,因此该版本将导致字典被解除分配。

此外,您的大部分dictionaryItems方法都无用。

[dictionaryLock lock];
if (dictionary == nil) {
    [self initialize];
}
[dictionaryLock unlock];

除非您使用+initialize方法,否则在您的类上调用任何其他方法之前,运行时会自动调用+load方法。由于运行时将为您调用它并且它将尝试创建字典,因此如果没有足够的内存来创建字典,则字典在dictionaryItems方法中只能是nil,在这种情况下它将再次失败。此外,如果您不在其他任何地方使用锁,也不必使用,因为删除该检查会导致锁定并立即解锁。因此,您可以移除锁定并将dictionaryItems方法更改为:

+ (NSDictionary *)dictionaryItems {
    return dictionary;
}

答案 1 :(得分:2)

除了@ ughoavgfhw的答案之外,您还在锁定它之后初始化dictionaryLock 。除非您在其他地方初始化dictionaryLock,否则我会惊讶于您的代码已经达到了目标。

编辑:我从@ ughoavgfhw的编辑中看到+initialize之前被调用,所以你的锁在那里被初始化。