将自定义对象写入 Cocoa 中的 .plist

发布于 2024-11-18 03:02:53 字数 2759 浏览 1 评论 0原文

我正在阻挡某物,并且我确信它太大了。 我有一个看起来像这样的自定义对象

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

downloadArrayNSMutableArray 时。我的 plist 读/写没问题,path 位于应用程序支持中,当我登录时它会显示 plist 路径。

但它只是不将数组写入 plist,知道吗?

I am blocking into something and I am sure it is too big.
I have a custom object that look like this

 @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

And the implementation

  @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

As you can see it implement NSCoding (I think so, NSObject does not conform to NSCoding). Now when I try to do something like that just to test

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 is a NSMutableArray. My plist read/write is fine, the path is located in the application support and when I log it show the plist path.

But it just does not write the array to the plist, any idea ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

空城仅有旧梦在 2024-11-25 03:02:53

属性列表文件只能存储基本数据类型,不能包含自定义对象。如果您希望将对象写入 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。您应该重新阅读 Objective-C 内存管理指南

Property list files can only store basic data types and cannot contain custom objects. You need to convert your object to an NSData object if you want it to be written to the plist. You can do this with NSKeyedArchiver, which will encode an object which conforms to the NSCoding protocol into an NSData object.

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

When you want to reconstruct your object from the NSData object, you use NSKeyedUnarchiver:

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

You also have several memory leaks in your code. In your -initWithCoder: method, you should not be using accessors to set the value of the ivars, you should just set the ivars directly, like so:

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

You are calling -retain and then using the accessor which is specified as copy, which will mean your object has a retain count of 2 and will not be released. In general you should avoid using accessors in init methods.

Also, in the code where you allocate your downloadArray object, you are calling -alloc and then -retain on the object, which will leave it with a retainCount of 2. You should re-read the Objective-C Memory Management Guidelines.

阳光下的泡沫是彩色的 2024-11-25 03:02:53

这对我有用:

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

This works for me:

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];
落花浅忆 2024-11-25 03:02:53
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");
}
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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文