objective c - Escribir objeto personalizado para.plist en Cocoa
objective-c nsobject (3)
Esto funciona para mí:
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:highScoreArray forKey:kHighScoreArrayKey];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
[data release];
[archiver release];
Estoy bloqueando algo y estoy seguro de que es demasiado grande. Tengo un objeto personalizado que se parece a esto
@interface DownloadObject : NSObject <NSCoding>{
NSNumber *key;
NSString *name;
NSNumber *progress;
NSNumber *progressBytes;
NSNumber *size;
NSString *path;
}
@property (copy) NSNumber *key;
@property (copy) NSString *name;
@property (copy) NSNumber *progress;
@property (copy) NSNumber *size;
@property (copy) NSString *path;
@property (copy) NSNumber *progressBytes;
-(id)initWithKey:(NSNumber *)k name:(NSString *)n progress:(NSNumber *)pro size:(NSNumber *)s path:(NSString *)p progressBytes:(NSNumber *)pb;
@end
Y la implementación
@implementation DownloadObject
@synthesize size, progress, name, key, path, progressBytes;
-(id)initWithKey:(NSNumber *)k name:(NSString *)n progress:(NSNumber *)pro size:(NSNumber *)s path:(NSString *)p progressBytes:(NSNumber *)pb
{
self.key = k;
self.name = n;
self.progress = pro;
self.size = s;
self.path = p;
self.progressBytes = pb;
return self;
}
-(id) initWithCoder: (NSCoder*) coder {
if (self = [super init]) {
self.key = [[coder decodeObjectForKey:@"Key"] retain];
self.name = [[coder decodeObjectForKey:@"Name"] retain];
self.progress = [[coder decodeObjectForKey:@"Progress"] retain];
self.size = [[coder decodeObjectForKey:@"Size"] retain];
self.path = [[coder decodeObjectForKey:@"Path"] retain];
self.progressBytes = [[coder decodeObjectForKey:@"ProgressBytes"]retain];
}
return self;
}
-(void) encodeWithCoder: (NSCoder*) coder {
[coder encodeObject:self.key forKey:@"Key"];
[coder encodeObject:self.name forKey:@"Name"];
[coder encodeObject:self.progress forKey:@"Progress"];
[coder encodeObject:self.size forKey:@"Size"];
[coder encodeObject:self.path forKey:@"Path"];
[coder encodeObject:self.progressBytes forKey:@"ProgressBytes"];
}
-(void)dealloc
{
[key release];
[name release];
[size release];
[progress release];
[path release];
[progressBytes release];
[super dealloc];
}
@end
Como puede ver, implementa NSCoding (creo que sí, NSObject no se ajusta a NSCoding). Ahora cuando trato de hacer algo así solo para probar
downloadArray = [[[NSMutableArray alloc]init]retain];
NSNumber *number = [NSNumber numberWithInt:10];
DownloadObject *object = [[DownloadObject alloc]initWithKey:number name:@"hey" progress:number size:number path:@"hey" progressBytes:number];
[downloadArray addObject:object];
[object release];
[downloadArray writeToFile:path atomically:YES];
downloadArray
es un NSMutableArray
. Mi lectura / escritura es buena, la path
se encuentra en el soporte de la aplicación y cuando la registro muestra la ruta de plist.
Pero simplemente no escribe la matriz en el plist, ¿alguna idea?
Los archivos de lista de propiedades solo pueden almacenar tipos de datos básicos y no pueden contener objetos personalizados. Necesita convertir su objeto a un objeto NSData
si desea que se escriba en el plist. Puede hacer esto con NSKeyedArchiver
, que codificará un objeto que se ajuste al protocolo NSCoding
en un objeto NSData
.
DownloadObject *object = [[DownloadObject alloc]initWithKey:number name:@"hey" progress:number size:number path:@"hey" progressBytes:number];
NSData* objData = [NSKeyedArchiver archivedDataWithRootObject:object];
[downloadArray addObject:objData];
[object release];
Cuando desee reconstruir su objeto desde el objeto NSData
, use NSKeyedUnarchiver
:
NSData* objData = [downloadArray objectAtIndex:0];
DownloadObject* object = [NSKeyedUnarchiver unarchiveObjectWithData:objData];
También tiene varias pérdidas de memoria en su código. En su método -initWithCoder:
no debería utilizar accesos para establecer el valor de los ivars, solo debe establecer los ivars directamente, de esta forma:
key = [[coder decodeObjectForKey:@"Key"] copy];
Está llamando -retain
y luego usa el acceso que se especifica como copy
, lo que significa que su objeto tiene un conteo retenido de 2 y no será liberado. En general, debe evitar el uso de accesos en los métodos init.
Además, en el código donde asigna su objeto downloadArray
, está llamando -alloc
y luego -retain
en el objeto, que lo dejará con un retainCount de 2. Debe volver a leer las Directrices de administración de memoria de Objective-C.
BOOL flag = false;
ObjectFileClass *obj = [yourMutableArray objectAtIndex:0];
//TO Write Data . . .
NSData* archiveData = [NSKeyedArchiver archivedDataWithRootObject:obj.title];
flag =[archiveData writeToFile:path options:NSDataWritingAtomic error:&error];
}
if (flag) {
NSLog(@"Written");
//To Read Data . . .
NSData *archiveData = [NSData dataWithContentsOfFile:path];
id yourClassInstance = [NSKeyedUnarchiver unarchiveObjectWithData:archiveData]; // choose the type of your class instance . . .
NSLog(@"%@",yourClassInstance);
}else{
NSLog(@"Not Written");
}