2

私の iOS アプリのアップデートが App Store で公開されたので、やけどを負いました。残念ながら、新しい機能を使用すると、私のコードでNSUserDefaults. 私のアプリは を使用していますregisterDefaultsが、新機能はアップグレード後に存在しないキーに書き込もうとします。によってキーが作成されるため、最初からインストールしても問題なく動作しregisterDefaultsます。

具体的には、私のアプリはネストされた辞書を使用しているため、更新前の設定ファイルは次の構造になっています。

<dict>
    <key>Alpha</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
    <key>Beta</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
    <key>Charlie</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
</dict>

—更新後、キーDeltaが必要です。

<dict>
    <key>Alpha</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
    <key>Beta</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
    <key>Charlie</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
    <key>Delta</key>
    <dict>
        <key>Key</key>
        <string>Value</string>
    </dict>
</dict>

いくつかのキーと値を書き込むためにユーザーのデフォルトからDeltaの辞書を取得しようとすると、コードが失敗します。このシナリオの辞書はnil、更新後に環境設定ファイルにないためです。

この状況を処理するためのベストプラクティスの方法は何ですか? Deltaのディクショナリnilに書き込む前に、必要に応じてそれを作成するかどうかを確認するだけですか、それともベルトとブレースのアプローチが少ないですか?

4

2 に答える 2

1

私はあなたのデータを使って簡単なテストを行いました:

  1. defaults.plistファイルを空のプロジェクトに追加します。

  2. defaults.plistを設定して、Alpha / Beta / Charlieキーを含めます(例のとおり)。

  3. appDidFinishLaunching時に次のコードを使用します。

    NSString* path = [[NSBundle mainBundle] pathForResource:@"defaults" ofType:@"plist"];
    NSDictionary* factoryPrefs = [NSMutableDictionary dictionaryWithContentsOfFile:path];
    [[NSUserDefaults standardUserDefaults] registerDefaults:factoryPrefs];
    NSLog(@"Delta Key: %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"Delta"]);
    
    //-- store some user custom values
    NSLog(@"Charlie Key %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"Charlie"]);
    [[NSUserDefaults standardUserDefaults] setObject:@"test" forKey:@"Charlie"];
    NSLog(@"Charlie Key %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"Charlie"]);
    
  4. アプリを実行します。

結果は次のとおりです。

2013-02-23 17:59:10.795 JigSaw[14747:c07] Delta Key (null)
2013-02-23 17:59:10.797 JigSaw[14747:c07] Charlie Key {
    Key = Value;
}
2013-02-23 17:59:10.797 JigSaw[14747:c07] Charlie Key test

次に、Deltaキーを追加してdefaults.plistのコンテンツを変更し(これも例のように)、アプリを再度ビルド/実行しました(もちろん、デバイスから削除することはありません)。

結果は次のとおりです。

2013-02-23 18:00:37.840 JigSaw[15040:c07] Delta Key {
    Key = Value;
}
2013-02-23 18:00:37.842 JigSaw[15040:c07] Charlie Key test
2013-02-23 18:00:37.842 JigSaw[15040:c07] Charlie Key test

したがって、registerDefaults上記の例のように使用すると、新しく追加されたキーを正しく処理できるようです。

registerDefaults間違って使用しているか、クラッシュの原因となっている他の場所で何かをしていると思う傾向があります。

より一般的なレベルでは、アプリの更新シナリオをテストすることは別として(事後に提案するのは簡単であり、私たちは皆、何らかの方法でそれを難し​​い方法で学びました)、私にとっての良い習慣は、あなたのアプリが確実に実行することです。間違った入力や予期しない入力があってもクラッシュしません。

于 2013-02-23T17:03:15.430 に答える
1

これらの状況を回避するために私が従うパターンは次のとおりです。

私の ApplicationDelegate+(void)initializeメソッドでは、キーとそのデフォルトを次のようにセットアップして、セットアップ前にデフォルトに触れないようにします。

+(void)initialize
{
    NSDictionary *factoryPrefs = @{MyNewPrefKey:@"ANewPrefKeyDefaultValue"};
}
[[NSUserDefaults standardUserDefaults] registerDefaults:factoryPrefs];
userSettings = [NSUserDefaults standardUserDefaults];

次に、この直後に、現在のバージョンに基づいて、ユーザーがアップグレードしていたことを示す以前の値 (新規ではない) の存在のチェックを開始するコード ブロックがあります。その場合、設定を移行/更新する必要があります。

たとえば、以前のバージョンでは a、b、c の値を持つ NSDictionary オブジェクトを保存していたが、このバージョンでは、キーを変更したり、値を挿入したりする必要がある場合があります。「d」値に応じて(および仮定して)、そこにもあります。

あなたが指摘したように、値は以前に作成されたので、その場合registerDefaultsは役に立ちません。したがって、「d」がそこにあるかどうかを手動で確認し、そうでない場合はデフォルト値とともに挿入する必要があります。これは、Prefs に相当する CoreData 移行の一種です :)

それが私がすることです。宗教的にやっています。私はリリースごとにチェックしています。そして、私たちは皆、次に何が起こるかを知っています.あなたは深刻な1つ星を獲得します..App Storeで大騒ぎします.

于 2013-02-23T14:22:13.170 に答える