web-dev-qa-db-ja.com

NSArrayをNSUserDefaultsに保存すると、アプリがクラッシュします

NSArrayをNsUserDefaultsに保存できませんでした。アプリがクラッシュする
この行の[savedData setObject:jsonValue forKey:@"JSONDATA"];

以下は私のコードです。そして私は以下に私のログエラーについて言及しました

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];
[savedData setObject:jsonValue forKey:@"JSONDATA"];
[savedData synchronize];

エラーログ:

*** Terminating app due to uncaught exception '`NSInvalidArgumentException`', reason: '*** -

[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object <CFBasicHash 0x8c62b10 [0x1d2aec8]>{type = immutable dict, count = 3,
    entries =>
13
iworld

はい、このようにNSUserDefaultsに保存することはできません。

私は以下のコードを書いています。見てください。さらに研究するには、Apple docsok。

コードはここにあります:

//保存用

NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:yourArrayToBeSave]];
[[NSUserDefaults standardUserDefaults] setObject:dataSave forKey:@"array"];

[[NSUserDefaults standardUserDefaults] synchronize]; // this will save you UserDefaults

//取得用

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"];
NSArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
43
kshitij godara

Kshitijの答えは正しいですが、悲しいことに、それだけではありません。カスタムオブジェクトをNSUserDefaults内に保存する場合、カスタムオブジェクトはNSCodingプロトコルを実装し、initWithCoderメソッドとencodeWithCoderメソッドをオーバーライドする必要があります。そのような例は次のようになります。

@interface Book : NSObject <NSCoding>
@property NSString *title;
@property NSString *author;
@property NSUInteger pageCount;
@property NSSet *categories;
@property (getter = isAvailable) BOOL available;
@end

@implementation Book

#pragma mark - NSCoding

    - (id)initWithCoder:(NSCoder *)decoder {
        self = [super init];
        if (!self) {
            return nil;
        }

        self.title = [decoder decodeObjectForKey:@"title"];
        self.author = [decoder decodeObjectForKey:@"author"];
        self.pageCount = [decoder decodeIntegerForKey:@"pageCount"];
        self.categories = [decoder decodeObjectForKey:@"categories"];
        self.available = [decoder decodeBoolForKey:@"available"];

        return self;
    }

    - (void)encodeWithCoder:(NSCoder *)encoder {
        [encoder encodeObject:self.title forKey:@"title"];
        [encoder encodeObject:self.author forKey:@"author"];
        [encoder encodeInteger:self.pageCount forKey:@"pageCount"];
        [encoder encodeObject:self.categories forKey:@"categories"];
        [encoder encodeBool:[self isAvailable] forKey:@"available"];
    }

@end
3
avismara

JsonValueはNSArrayではなくNSDictionaryだと思います。

 id jsonValue = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
    if ([jsonValue isKindOfClass:[NSDictionary class]])
    {
   NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue];
   [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"];
    [savedData synchronize];
    }

//(または)

NSDictionary *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"];
[savedData synchronize];

また、NSDictionaryをNSUserDefaultsに直接保存することはできないと思います。@ kshitijgodaraを使用して、完了/保存してください。

NSKeyedArchiverを使用して、辞書をNSDataに書き出すことができます。

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"];

データを取得する場合:

NSData *dictionaryData = [defaults objectForKey:@"JSONDATA"];
NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:dictionaryData];

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

1
Vidhyanand

このようにしてみてください

 NSMutableArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSData *yourEncodedObject = [NSKeyedArchiver archivedDataWithRootObject: jsonValue];

       NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];
        [userData setObject: yourEncodedObject forKey:@"JSONDATA"];
    [savedData synchronize];
1
Sport

NSUserDefaultsは、プロパティリストオブジェクト(NSDictionary、NSArray、NSString、NSNumber、NSDate、NSData)を受け入れます。 JSONドキュメントには、NSDictionary、NSArray、NSString、NSNumber、NSNullが含まれています。違いがわかります。プロパティリストオブジェクトにNSNull値を含めることはできません。

JSONオブジェクトにNSNullオブジェクトが含まれている場合(解析したJSONドキュメントに「null」値が含まれている場合)、NSUserDefaultsに保存することはできません。それとは別に、JSONデータをNSUserDefaultsに保存できないというコメントはすべて意味がありません。問題を引き起こすのはNSNullオブジェクトだけです。

あなたの問題には非常に簡単な解決策があります。元のjsonデータをNSDataオブジェクトとしてNSUserDefaultsに保存するだけです。次に、NSUserDefaultsを読み取ると、NSDataを取得して解析します。の代わりに

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];
[savedData setObject:jsonValue forKey:@"JSONDATA"];
[savedData synchronize];

あなたはただ書く

NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];
[savedData setObject:data forKey:@"JSONDATA"];
[savedData synchronize];
1
gnasher729

最初にNSArrayを割り当てる必要があります。その後、配列に値を渡すことができます。値を直接渡すことはできません。

NSArray * a = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]、nil];

0
Arjun Gupta

NSUserDefaultsは、最大500kのデータにのみ使用する必要があります( https://forums.developer.Apple.com/message/50696#50696

大量のアプリを保存するとクラッシュする可能性がある場合、個人的な経験から、[NSUserDefaults setObject:]と[NSUserDefaultssynchronise]の直後に1MBのデータを保存しているアプリがクラッシュするのを見ました。

ライブアプリが使用しているデータの量を確認するには、[Xcode]-> [ウィンドウ]-> [デバイス]を開き、デバイスを選択し、[インストール済みアプリ]でアプリを選択して、アプリコンテナをダウンロードします。デフォルトはAppData-> Preferences-> your.app.plistに保存されます

ユーザーのデフォルトにデータを保存する代わりに、ファイルに書き込むこともできます。

-(void)saveObject:(NSObject *)object toFile:(NSString *)name {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name];
    [NSKeyedArchiver archiveRootObject:object toFile:appFile];
}

-(NSObject *)loadFromFile:(NSString *)name {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name];

    if([[NSFileManager defaultManager] fileExistsAtPath:appFile])
        return [NSKeyedUnarchiver unarchiveObjectWithFile:appFile];
    else{
        NSLog(@"No File: %@", name) ;
        return nil ;
    }

}
0
A.Badger