2011-07-14 18 views
11

En mi aplicación para iPhone, tengo una clase llamada Contact que consiste en ABRecordRef para servir como referencia a un contacto en particular.Almacenar datos en NSUserDefaults

Necesito almacenar grupos de estos contactos en NSUserDefaults, pero las cosas no están saliendo tan bien ya que Contact es una clase personalizada.

¿Alguna idea de qué hacer en este caso?

Respuesta

29

No puede usar NSUserDefaults para una clase personalizada. A partir de la documentación:

El NSUserDefaults clase proporciona métodos de conveniencia para acceder tipos comunes tales como flotadores, dobles, números enteros, booleanos y URL. Un objeto predeterminado debe ser una lista de propiedades, es decir, una instancia de (o para las colecciones de una combinación de las instancias de): NSData, NSString, NSNumber, NSDate, NSArray, o NSDictionary. Si desea almacenar cualquier otro tipo de objeto , normalmente debe archivarlo para crear una instancia de NSData.

Probar usando NSData. Por ejemplo, la carga de objetos personalizados en una matriz, que puede hacer

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

Para archivar los datos, utilice:

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

Esto hará todo el trabajo, siempre y cuando el objeto personalizado cumple con el protocolo 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 es un tipo C opaco, por lo que no es un objeto en el sentido de Objective-C. Eso significa que no puede ampliarlo, no puede agregar una categoría, no puede enviarlo por mensaje. Lo único que puede hacer es llamar a las funciones descritas en ABRecord Referencia con ABRecord como parámetro.

Se podía hacer dos cosas para ser capaz de mantener la información que hace referencia la ABRecord en torno a:

  1. Consigue el ABRecord s id por ABRecordGetRecordID(). El ABRecordID se define como int32_t para que pueda convertirlo a NSInteger y almacenarlo donde desee. Luego puede recuperar la grabación desde ABAddressBookGetPersonWithRecordID() o ABAddressBookGetGroupWithRecordID(). Sin embargo, el registro podría ser modificado o incluso borrado por el usuario o por otra aplicación mientras tanto.

  2. Copie todos los valores dentro del registro en una subclase estándar NSObject y utilice NSCoding como se indicó anteriormente para almacenarlo. Por supuesto, no se beneficiará de los cambios o adiciones al registro que el usuario podría haber realizado.

+0

Pero no puedo codificar ABRecordRef porque aparentemente no es un objeto. – CodeGuy

+0

bien, hice todo eso. pero ¿cómo codifico ABRecordRef – CodeGuy

+0

@ reising1: ver arriba. – PengOne

1

ABRecordRef parece ser un const void *, por lo que almacenarlo en NSUserDefaults, usted tiene que envolverlo en NSData: NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];.

+0

sí, pero ¿cómo almaceno un ABRecordRef, ya que aparentemente no es un objeto – CodeGuy

+0

, ¿sabe al menos de qué se trata? objeto, estructura, tipo de base? –

2

Bueno, Apple's recommendation es para almacenar el identificador de registro, el primer nombre y el apellido. A continuación, puede intentar recuperar el contacto de la libreta de direcciones mediante el identificador y, si no encuentra el registro o si no es la persona adecuada, intente recuperar por nombre y apellido (ya que los identificadores de registro pueden cambiar según la fuente de su datos de la libreta de direcciones).

Esto puede ser o no lo que desee, dependiendo de por qué está almacenando los datos. Pero, podría fácilmente poner esos tres valores en un NSDictionary y escribir el diccionario en NSUserDefaults.

0

Puede almacenarlo en realidad mediante la conversión a la representación vCard, que es CFStringRef, que se puede usar fácilmente como NSString.

Cuestiones relacionadas