2011-07-14 6 views
11

Dans mon application iPhone, j'ai une classe appelée Contact qui consiste en un ABRecordRef servant de référence à un contact particulier.Stockage des données dans NSUserDefaults

J'ai besoin de stocker des groupes de ces contacts dans NSUserDefaults, mais les choses ne fonctionnent pas si bien car Contact est une classe personnalisée.

Une idée de ce qu'il faut faire dans ce cas?

Répondre

29

Vous ne pouvez pas utiliser NSUserDefaults pour une classe personnalisée. De la documentation:

La classe NSUserDefaults fournit des méthodes pratiques pour accéder à types communs tels que flotteurs, doubles, entiers, booléens et URL. Un objet par défaut doit être une liste de propriétés, qui est une instance de (ou pour les collections d'une combinaison d'instances de): NSData, NSString, NSNumber, NSDate, NSArray ou NSDictionary. Si vous souhaitez stocker un autre type d'objet, vous devez généralement l'archiver pour créer une instance de NSData.

Essayez d'utiliser NSData. Par exemple, pour charger des objets personnalisés dans un tableau, vous pouvez faire

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"]; 
if (dataRepresentingSavedArray != nil) 
{ 
     NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray]; 
     if (oldSavedArray != nil) 
       objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray]; 
     else 
       objectArray = [[NSMutableArray alloc] init]; 
} 

Pour archiver les données, utilisez:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"]; 

Ce sera tout le travail aussi longtemps que votre objet personnalisé conforme au protocole NSCoding :

- (void)encodeWithCoder:(NSCoder *)coder; 
{ 
    [coder encodeObject:label forKey:@"label"]; 
    [coder encodeInteger:numberID forKey:@"numberID"]; 
} 

- (id)initWithCoder:(NSCoder *)coder; 
{ 
    self = [[CustomObject alloc] init]; 
    if (self != nil) 
    { 
     label = [coder decodeObjectForKey:@"label"]; 
     numberID = [coder decodeIntegerForKey:@"numberID"]; 
    } 
    return self; 
} 

ABRecord est un type opaque C, il est donc pas un objet dans le sens de l'Objective-C. Cela signifie que vous ne pouvez pas l'étendre, vous ne pouvez pas ajouter une catégorie, vous ne pouvez pas le signaler. La seule chose que vous pouvez faire est d'appeler les fonctions décrites dans ABRecord Référence avec le ABRecord en tant que paramètre.

Vous pouvez faire deux choses pour être en mesure de garder l'information référencée par la ABRecord autour de:

  1. Obtenez le ABRecord s id par ABRecordGetRecordID(). Le ABRecordID est défini comme int32_t, vous pouvez donc le convertir en NSInteger et le stocker où vous le souhaitez. Vous pouvez plus tard récupérer l'enregistrement de ABAddressBookGetPersonWithRecordID() ou ABAddressBookGetGroupWithRecordID(). Cependant, l'enregistrement pourrait être modifié ou même supprimé par l'utilisateur ou une autre application en attendant.

  2. Copiez toutes les valeurs de l'enregistrement dans une sous-classe NSObject standard et utilisez NSCoding comme indiqué ci-dessus pour le stocker. Bien entendu, vous ne bénéficierez pas des modifications ou des ajouts apportés à l'enregistrement que l'utilisateur aurait pu effectuer.

+0

Mais je ne peux pas encoder ABRecordRef parce que ce n'est pas un objet. – CodeGuy

+0

droite, j'ai fait tout cela. mais comment puis-je encoder ABRecordRef – CodeGuy

+0

@ reising1: Voir ci-dessus. – PengOne

1

ABRecordRef semble être un const void *, donc le stocker dans NSUserDefaults, vous devez envelopper dans NSData: NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];.

+0

oui, mais comment puis-je stocker un ABRecordRef, puisque ce n'est pas un objet apparemment – CodeGuy

+0

savez-vous au moins ce que c'est? objet, struct, type de base? –

2

Eh bien, Apple's recommendation est de stocker l'identifiant d'enregistrement, le prénom et le nom de famille. Vous pouvez ensuite essayer de récupérer le contact du carnet d'adresses par l'identifiant et, si l'enregistrement n'est pas trouvé ou si ce n'est pas la bonne personne, essayez d'extraire par nom et prénom (puisque les identifiants d'enregistrement peuvent changer selon la source de votre données du carnet d'adresses).

Cela peut ne pas être ce que vous voulez, selon la raison pour laquelle vous stockez les données. Mais, vous pouvez facilement mettre ces trois valeurs dans un NSDictionary et écrire le dictionnaire à NSUserDefaults.

0

Vous pouvez le stocker en utilisant la conversion en représentation vCard, qui est CFStringRef, qui peut être facilement utilisée comme NSString.

Questions connexes