2011-07-13 16 views
1

plistファイルから辞書項目を読み込む小さなクラスを作成しました。 getSettingForKeyメソッドは静的メソッドを初めて呼び出すときに機能しますが、少数の呼び出しの後に、辞書は前の呼び出しで働いたのと同じキーを持つ呼び出しに対してSIGABRT例外をスローします。何か案は?Objective-C静的フィールドの問題

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 

モシェ - 私はあなたの提案を取り、代わりに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

NSUserDefaultsというクラスがあります。これは、あなたが望むことを達成する可能性が高いでしょう。 – Moshe

+0

はい、私はユーザーアプリケーションの設定にNSUserDefaultsを使用します。いくつかの設定URLと非ユーザ設定を読むために、plistファイルからそれらの設定を読みたいだけです。 – mservidio

答えて

8

あなたの辞書はおそらく不正なメモリアクセスを引き起こし、割り当て解除されました。 dictionaryWithContentsOfFile:メソッドを使用して辞書を作成すると、オートレリースされます。これは、自動的に将来リリースされることを意味します。あなたは辞書を保持しないので、そのリリースは辞書の割り当てを解除します。

また、ほとんどのdictionaryItemsメソッドは役に立たないです。

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

他の方法は、あなたのクラスで呼び出される前に、あなたが+loadメソッドを持っていない限り、+initialize方法は自動的に、ランタイムによって呼び出されます。ランタイムはそれを呼び出して辞書を作成しようとするので、辞書は作成するメモリが不足している場合には、dictionaryItemsメソッドではnilになることがあります。また、他の場所でロックを使用しない場合は、そのチェックを削除するとロックが解除され、すぐにロックが解除されるため、ロックは不要です。したがって、あなたがロックを解除し、単純に自分のdictionaryItems方法を変更することができます。

+ (NSDictionary *)dictionaryItems { 
    return dictionary; 
} 
+0

お返事ありがとうございます。私は通常C#をやっているので、ガベージコレクションについて心配する必要はありません。 – mservidio

+0

ルールは簡単です。 「私はそれに慣れていない」という理由だけでそれらを無視する理由はありません。 'alloc'、' new'、 'copy'、または' retain'を呼び出すたびに、メモリを解放する必要があります。 'autorelease'コールはautoreleaseプールが次に流出するたびにメモリを解放するようにアプリケーションに指示します。通常、自動解放されたオブジェクトは、メソッド呼び出しが終了するまで使用可能になることが保証されますが、それ以上は使用できません。 – Moshe

2

@のughoavgfhwの回答に加えて、あなたも、あなたがそれをロックしている後dictionaryLockを初期化しています。他の場所でdictionaryLockを初期化している場合を除き、あなたのコードが現状のものになっているのは驚きです。

編集:@ ughoavgfhwの編集から、+initializeが何よりも先に呼び出されているので、あなたのロックはそこで初期化されています。

関連する問題