Подтвердить что ты не робот

Приложение сбой при хранении 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 =>
4b9b3361

Ответ 1

Да, они не могут быть сохранены как в NSUserDefaults.

Я пишу код ниже, пожалуйста, посмотрите и для более подробного изучения посмотрите, как выглядят документы яблока.

Код находится здесь:

//Для сохранения

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];

Ответ 2

В то время как ответ 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

Я думаю, что jsonValue - это NSDictionary, а не NSArray..

 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. Пройдите через @kshitij godara, чтобы сделать это/сохранить.

Вы можете использовать NSKeyedArchiver для записи своего словаря в NSData.

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

Для получения данных:

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

Надеюсь, это поможет вам!..

Ответ 4

попробуйте это

 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];

Ответ 5

NSUserDefaults принимает объекты списка свойств - NSDictionary, NSArray, NSString, NSNumber, NSDate и NSData. Документы JSON содержат NSDictionary, NSArray, NSString, NSNumber и NSNull. Вы видите, что объекты списка различий - свойств не могут содержать значения NSNull.

Если ваш объект JSON содержит объект NSNull (в документе JSON, который вы проанализировали, содержится "нулевое" значение), вы не можете сохранить его в 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];

Ответ 6

Вы должны сначала выделить NSArray, тогда вы можете передать значения в массиве. Вы не можете напрямую передать значение.

NSArray * a = [[NSArray alloc] initWithObjects: [NSJSONSerialization JSONObjectWithData: параметры данных: 0 error: nil], nil];

Ответ 7

NSUserDefaults следует использовать только для 500 000 данных (https://forums.developer.apple.com/message/50696#50696)

При хранении больших объемов приложений приложения могут упасть, из личного опыта я видел приложения, в которых хранилось 1 МБ данных, сбой/вскоре после [NSUserDefaults setObject:] и [NSUserDefaults synchronize];

Чтобы проверить, сколько данных используется в реальном времени, откройте Xcode → Window → Devices, выберите ваше устройство, выберите ваше приложение в Installed Apps и загрузите App Container. Значения по умолчанию хранятся в 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 ;
    }

}