2009-12-12 7 views
3

je le code suivant qui devrait mettre à jour une valeur NSUserDefaults:Comment mettre à jour une NSUserDefault

- (id) createBoardWithTitle:(NSString *)pTitle withScores:(NSArray *)pScores andNames:(NSArray *)pNames andDisplayStrings:(NSArray *)pStrings orderBy:(NSString *)pOrder ofType:(NSString *)pType 
{ 

    if((self == [super init])) 
    { 

     boardEntries = [NSMutableArray arrayWithCapacity:10]; 

     // Build the data 

      for(...){ 
       // populate boardEntries 
      } 


     // create an Dictionary to save 
     NSDictionary *savedData = [NSDictionary dictionaryWithObjectsAndKeys:pType, @"type", pOrder, @"order", boardEntries, @"entries", nil]; 

      // Load the old boards 
     NSDictionary *existingBoards = [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]; 

      // Create a mutable dictionary to replace the old immutable dictionary 
     NSMutableDictionary *newBoards = [NSMutableDictionary dictionaryWithCapacity:[existingBoards count]+1]; 

      // transfer the old dictionary into the new dictionary 
     [newBoards addEntriesFromDictionary:existingBoards]; 

      // add the new board to the new dictionary 
     [newBoards setObject:savedData forKey:pTitle]; 

      // check to make sure it looks like it should by eye 
     NSLog(@"New Boards: %@", newBoards); 

      // Replace the old date in NSUserdefaults 
     [[NSUserDefaults standardUserDefaults] setObject:newBoards forKey:@"BlockDepotleaderboards"]; 
      // Update: Do I really need to call this? 
     [[NSUserDefaults standardUserDefaults] synchronize]; 

      // Check to make sure it looks as it should by eye 
     NSLog(@" Defaults--- %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]); 
    } 

    return self; 

} 

Pour autant que je peux dire, c'est le code pertinent. C'est probablement plus «verbeux» qu'il ne le faudrait peut-être. Mais si je comprends bien, tout ce qui est retourné par NSUserDefaults sera immuable, donc je dois le recréer comme un objet Mutable, ajouter ce qui doit être ajouté puis remplacer l'objet dans NSUserDefaults. Et je pense que ce que j'essaye ci-dessus devrait fonctionner.

la sortie pour NSLog (@ "De nouveaux conseils:% @", newBoards) id

New Boards: { 
    "Marathon: Times" =  { 
     entries =   (
         { 
       displayString = "10:00"; 
       name = "Tom Elders"; 
       score = 600; 
      }, 
         { 
       displayString = "10:30"; 
       name = "A.R. Elders"; 
       score = 630; 
      }, 
         { 
       displayString = "11:00"; 
       name = "L. Lancaster-Harm"; 
       score = 660; 
      }, 

      // and so on..... 

     ); 
     order = ASC; 
     type = TIMES; 
    }; 
    String = Test; 
} 

"String = test" est juste une entrée de test et est défini dans le fichier AppDelegate.m comme celui-ci:

if(![[NSUserDefaults standardUserDefaults] objectForKey:@"BlockDepotLeaderboards"]){ 

    NSMutableDictionary *leadboardHolder = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Test", @"String", nil];  
    [[NSUserDefaults standardUserDefaults] setObject:leadboardHolder forKey:@"BlockDepotLeaderboards"]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 



}else{ 
    NSLog(@"Leaderboards Dict Exists %@", [NSUserDefaults standardUserDefaults]); 
} 

Donc, je sais que ce que je suis après est définitivement là. Je sais juste que ça va être quelque chose de stupide qui me manque. Mais je ne peux pas le voir ou le comprendre.

Quelqu'un peut-il voir ce que je bousille?

+0

Ne pas faire 'objectForKey: @" BlockDepotLeaderboards "'. Vous n'avez aucune idée de ce que l'objet retourné sera réellement. Utilisez -dictionaryForKey: à la place, et manipulez le cas où il est nul en créant un nouveau dictionnaire. –

+0

Si vous accédez aux valeurs de NSUserDefaults vous devez soit utiliser dictionForKey: soit transcrire l'objet dans le dictionnaire –

Répondre

5

Pour autant que je peux dire, c'est le code pertinent. C'est probablement plus «verbeux» qu'il ne le faudrait peut-être. Mais si je comprends bien, tout ce qui est retourné par NSUserDefaults sera immuable, donc je dois le recréer comme un objet Mutable, ajouter ce qui doit être ajouté puis remplacer l'objet dans NSUserDefaults.

Un moyen plus facile est de faire un mutableCopy du dictionnaire immuable comme ceci:

NSMutableDictionary *newBoards = [[immutableDict mutableCopy] autorelease]; 
[newBoards setObject:savedData forKey:pTitle]; 

En outre, synchronize est utilisé pour forcer l'enregistrement des paramètres utilisateur par défaut sur le disque. Cela ne fait qu'influencer ce que vous voyez quand vous ouvrez le plist dans le Finder. Du point de vue de l'application NSUserDefaults est toujours à jour. En outre, les valeurs par défaut sont sauvegardées automatiquement chaque fois, donc la seule fois où vous aurez probablement besoin d'appeler synchronize est lorsque votre application se termine.

0

Selon les docs:

Un objet par défaut doit être une propriété liste , qui est une instance de (ou pour collections une combinaison des instances de): NSData, NSString, NSNumber, NSDate, NSArray ou NSDictionary.

Êtes-vous sûr de tous les objets que vous essayez de sérialiser? Jetez un oeil à NSKeyedArchiver

Regardez aussi cette question Why NSUserDefaults failed to save NSMutableDictionary in iPhone SDK?

+0

J'utilise NSKeyedArchiver ailleurs pour quelque chose d'autre. Ce projet est principalement un projet d'auto-enseignement, donc je veux obtenir ce clou. Mais je pensais la même chose; Pour autant que je sache, j'essaie de sauver un NSDictionary, avec deux NSStrings et un NSarray qui contient 10 NSDictionaries qui contiennent deux NSStrings et un NSNUmber. Mais je vais revenir en arrière et tripler vérifier. – gargantuan

0

Tout d'abord sauver quoi que ce soit:

[[NSUserDefaults standardUserDefaults] setObject:@"Previous Value" forKey:@"Name"]; 

Lancez ensuite ce code à nouveau pour mettre à jour la valeur de la même clé:

[[NSUserDefaults standardUserDefaults] setObject:@"Updated Value" forKey:@"Name"]; 

vous ne avez pas besoin d'appeler [[NSUserDefaults standardUserDefaults] Synchronize ] en raison de la performance issue.call il seulement nécessaire. iOS gère bien.

Vous n'avez pas besoin d'enlever d'objet. Juste mettre à jour la même clé. Il mettra à jour la valeur de cette clé particulière. J'espère que cela aide.