Написать пользовательский объект в .plist в Какао - PullRequest
5 голосов
/ 04 июля 2011

Я блокируюсь во что-то, и я уверен, что это слишком большое. У меня есть пользовательский объект, который выглядит так

 @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

И реализация

  @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

Как вы можете видеть, он реализует NSCoding (я так думаю, NSObject не соответствует NSCoding). Теперь, когда я пытаюсь сделать что-то подобное, просто чтобы проверить

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 является NSMutableArray. Мой plist для чтения / записи в порядке, path находится в поддержке приложения, и когда я вхожу в систему, отображается путь к plist.

Но это просто не записывает массив в plist, есть идеи?

Ответы [ 3 ]

21 голосов
/ 04 июля 2011

Файлы списка свойств могут хранить только базовые типы данных и не могут содержать пользовательских объектов.Вам нужно преобразовать ваш объект в NSData объект, если вы хотите, чтобы он был записан в список.Вы можете сделать это с помощью NSKeyedArchiver, который закодирует объект, соответствующий протоколу NSCoding, в объект 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];

Когда вы хотите восстановить свой объект из NSDataобъект, вы используете NSKeyedUnarchiver:

NSData* objData = [downloadArray objectAtIndex:0];
DownloadObject* object = [NSKeyedUnarchiver unarchiveObjectWithData:objData];

У вас также есть несколько утечек памяти в вашем коде.В вашем методе -initWithCoder: вы не должны использовать аксессоры для установки значения ivars, вы должны просто установить ivars напрямую, например так:

key = [[coder decodeObjectForKey:@"Key"] copy];

Вы звоните -retain и затем используетеметод доступа, который указан как copy, что означает, что ваш объект имеет счет сохранения 2 и не будет освобожден.В общем, вы должны избегать использования методов доступа в методах init.

Кроме того, в коде, где вы выделяете объект downloadArray, вы вызываете -alloc, а затем -retain для объекта, который покинет его.с retainCount 2. Вы должны перечитать Objective-C Руководство по управлению памятью .

0 голосов
/ 11 сентября 2016
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");
}
0 голосов
/ 04 июля 2011

Это работает для меня:

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];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...