web-dev-qa-db-fra.com

L'application se bloque lors du stockage de NSArray dans NSUserDefaults

Je ne pouvais pas stocker un NSArray dans NsUserDefaults. L'application est écrasée
dans cette ligne [savedData setObject:jsonValue forKey:@"JSONDATA"];

Ci-dessous mon code. et j'ai mentionner mon erreur de journal ci-dessous

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

Journal d'erreur:

*** 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

Oui, ils ne peuvent pas être sauvegardés comme ceci dans NSUserDefaults .

Je suis en train d'écrire un code ci-dessous s'il vous plaît jeter un oeil et pour plus d'étude allez regardez docs Apple d'accord.

Le code est ici:

// Pour sauvegarder

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

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

// Pour récupérer

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

Bien que la réponse de kshitij soit correcte, elle ne s'arrête malheureusement pas là. Si vous souhaitez enregistrer des objets personnalisés dans votre NSUserDefaults, celui-ci doit implémenter le protocole NSCoding et remplacer les méthodes initWithCoder et encodeWithCoder. Voici un exemple:

@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

Je pense que jsonValue est NSDictionary pas 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];
    }

//(OU)

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

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

De plus, je pense que vous ne pouvez pas stocker le NSDictionary directement dans NSUserDefaults..Allez via @kshitij godara pour le faire/sauvegarder ..

Vous pouvez utiliser NSKeyedArchiver pour écrire votre dictionnaire dans un NSData.

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

Pour récupérer des données:

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

J'espère que cela vous aide ..!

1
Vidhyanand

essayez comme ça 

 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 accepte les objets de liste de propriétés - NSDictionary, NSArray, NSString, NSNumber, NSDate et NSData. Les documents JSON contiennent NSDictionary, NSArray, NSString, NSNumber et NSNull. Vous voyez la différence: les objets de liste de propriétés ne peuvent pas contenir de valeurs NSNull.

Si votre objet JSON contient un objet NSNull (le document JSON que vous avez analysé contenait une valeur "null"), vous ne pouvez pas le stocker dans NSUserDefaults. En dehors de cela, tous les commentaires disant que vous ne pouvez pas stocker de données JSON dans NSUserDefaults sont absurdes. Ce ne sont que des objets NSNull qui posent problème. 

Il existe une solution très très simple à votre problème. Stockez simplement les données JSON d'origine en tant qu'objet NSData dans NSUserDefaults. Ensuite, lorsque vous lisez NSUserDefaults, vous obtenez NSData et vous les analysez. Au lieu de

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

tu viens d'écrire

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

Vous devez d’abord allouer NSArray pour pouvoir ensuite transmettre les valeurs dans un tableau. Vous ne pouvez pas passer directement la valeur.

NSArray * a = [[NSArray alloc] initWithObjects: [NSJSONSerialization JSONObjectWithData: options de données: 0 erreur: nil], nil];

0
Arjun Gupta

NSUserDefaults ne doit être utilisé que pour 500k maximum de données ( https://forums.developer.Apple.com/message/50696#50696 )

Si le stockage d’applications de plus grandes quantités risque de planter, j’ai vu par expérience que des applications stockaient 1 Mo de données se bloquant sur/peu après [NSUserDefaults setObject:] et [NSUserDefaults synchronize];

Pour vérifier la quantité de données utilisée par une application en direct, ouvrez Xcode -> Fenêtre -> Appareils, sélectionnez votre appareil, sélectionnez votre application dans Applications installées et téléchargez le conteneur d'applications. Les valeurs par défaut sont stockées dans AppData-> Préférences-> votre.app.plist

Une alternative à la sauvegarde des données sur les valeurs utilisateur par défaut consiste à écrire dans un fichier:

-(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