【问题标题】:Write custom object to .plist in Cocoa在 Cocoa 中将自定义对象写入 .plist
【发布时间】:2011-07-04 08:51:30
【问题描述】:

我挡住了一些东西,我确信它太大了。 我有一个看起来像这样的自定义对象

 @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,知道吗?

【问题讨论】:

  • 为什么将downloadArray的retainCount设置为2?只需要 downloadArray = [[NSMutableArray alloc]init];

标签: objective-c cocoa nsobject nscoding


【解决方案1】:

属性列表文件只能存储基本数据类型,不能包含自定义对象。如果要将对象写入 plist,则需要将对象转换为 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,这将使其保留计数为2。您应该重新阅读目标- CMemory Management Guidelines.

【讨论】:

  • 值得吗?我的意思是,这是否比将属性转换为字典并保存为字典更有效率?为什么我需要将我的对象包装到 nsdata 或者对此有什么建议?
【解决方案2】:

这对我有用:

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

【讨论】:

    【解决方案3】:
    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");
    }
    

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 2014-09-14
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 2014-05-28
      相关资源
      最近更新 更多