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 =>
はい、このように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];
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
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];
これがお役に立てば幸いです。
このようにしてみてください
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];
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];
最初にNSArrayを割り当てる必要があります。その後、配列に値を渡すことができます。値を直接渡すことはできません。
NSArray * a = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]、nil];
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 ;
}
}