web-dev-qa-db-ja.com

NSUserDefaultsがiOSでNSMutableDictionaryを保存できなかったのはなぜですか?

NSMutableDictionaryオブジェクトをNSUserDefaultsに保存したいのですが。 NSMutableDictionaryのキータイプはNSStringで、値のタイプはNSArrayです。これには、NSCodingを実装するオブジェクトのリストが含まれます。ドキュメントごとに、NSStringNSArrayは両方ともNSCodingに準拠しています。

このエラーが発生しています:

[NSUserDefaults setObject:forKey:]:クラスNSCFDictionaryのプロパティ以外の値を挿入しようとしました。

145
BlueDolphin

保存する前に、NSArrayで終わるNSKeyedArchiverを使用してルートオブジェクト(NSDataオブジェクト)をエンコードします。次に、UserDefaultsを使用してNSDataを保存します。

データが必要になったら、NSDataを読み取り、NSKeyedUnarchiverを使用してNSDataをオブジェクトに戻します。

NSDataに毎回/から変換する必要があるので、少し面倒ですが、それだけで機能します。

リクエストごとに1つの例を示します。

セーブ:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *arr = ... ; // set value
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[defaults setObject:data forKey:@"theKey"];
[defaults synchronize];

負荷:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"theKey"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

配列内の要素は実装します

@interface CommentItem : NSObject<NSCoding> {
    NSString *value;
}

次に、CommentItemの実装で、2つのメソッドを提供します。

-(void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:value forKey:@"Value"];
}

-(id)initWithCoder:(NSCoder *)decoder
{
    self.value = [decoder decodeObjectForKey:@"Value"];
    return self;
}

誰もがより良い解決策を持っていますか?

みんな、ありがとう。

230
BlueDolphin

オブジェクトをユーザーのデフォルトで保存する場合、すべてのオブジェクトは、再帰的に、ずっと下まで、プロパティリストオブジェクトでなければなりません。 NSCodingに準拠することは、ここでは何の意味もありません。NSUserDefaultsは自動的にNSDataにエンコードしません。自分でそれを行う必要があります。 「NSCodingを実装するオブジェクトのリスト」がプロパティリストオブジェクトではないオブジェクトを意味する場合、ユーザーのデフォルトに保存する前にそれらを使用する必要があります。

参考までに、プロパティリストクラスはNSDictionaryNSArrayNSStringNSDateNSData、およびNSNumberです。可変サブクラス(NSMutableDictionaryなど)をユーザー設定に書き込むことができますが、読み出したオブジェクトは常に不変です。

105
Tom Harrington

すべてのキーは辞書NSStringsにありますか?辞書をプロパティリストに保存するためには、それらが必要だと思います。

14
Sophie Alpert

最も簡単な答え:

NSDictionaryは、キーがNSStringsの場合のみplistオブジェクトです。したがって、"Key"NSStringとともにstringWithFormatとして保存します。


解決策:

NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];

利点:

  1. String-Valueを追加します。
  2. 変数の値がNULLの場合、Empty-Valueが追加されます。
7
Bhavin

NSCodingプロトコルの実装を検討したことがありますか?これにより、NSCodingで実装される2つの単純なメソッドを使用して、iPhoneでエンコードとデコードを行うことができます。最初に、NSCodingをクラスに追加する必要があります。

以下に例を示します。

これは.hファイルにあります

@interface GameContent : NSObject <NSCoding>

次に、NSCodingプロトコルの2つのメソッドを実装する必要があります。

    - (id) initWithCoder: (NSCoder *)coder
    {
        if (self = [super init])
        {
               [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]];
        }
        return self;
    }

    - (void) encodeWithCoder: (NSCoder *)coder
    {
           [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
    }

詳細については、NSCoderのドキュメントをご覧ください。これは、アプリケーションを閉じた場合にアプリケーションの状態をiPhoneに保存し、再びオンになったときに元の状態に戻す必要があるプロジェクトで非常に便利です。

重要なのは、インターフェイスにプロトコルを追加し、NSCodingの一部である2つのメソッドを実装することです。

これがお役に立てば幸いです!

5
Niels Hansen

これ以上の解決策はありません。別のオプションは、コード化されたオブジェクトをディスクに保存することです-しかし、それは同じことをしています。どちらもNSDataになり、NSDataは元に戻すときにデコードされます。

0
Dan Keen