Objective-C静态字段问题

mse*_*dio 1 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
Run Code Online (Sandbox Code Playgroud)

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];
}
Run Code Online (Sandbox Code Playgroud)

ugh*_*fhw 8

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

此外,你的大部分dictionaryItems方法都是无用的.

[dictionaryLock lock];
if (dictionary == nil) {
    [self initialize];
}
[dictionaryLock unlock];
Run Code Online (Sandbox Code Playgroud)

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

+ (NSDictionary *)dictionaryItems {
    return dictionary;
}
Run Code Online (Sandbox Code Playgroud)