将自定义对象写入 Cocoa 中的 .plist
我正在阻挡某物,并且我确信它太大了。 我有一个看起来像这样的自定义对象
@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,知道吗?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
属性列表文件只能存储基本数据类型,不能包含自定义对象。如果您希望将对象写入 plist,则需要将其转换为
NSData
对象。您可以使用NSKeyedArchiver
来完成此操作,它会将符合NSCoding
协议的对象编码为NSData
对象。当您想要从
NSData
对象重建对象时,您可以使用NSKeyedUnarchiver
:您的代码中还会存在一些内存泄漏。在您的
-initWithCoder:
方法中,您不应该使用访问器来设置 ivars 的值,您应该直接设置 ivars,如下所示:您正在调用
-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 withNSKeyedArchiver
, which will encode an object which conforms to theNSCoding
protocol into anNSData
object.When you want to reconstruct your object from the
NSData
object, you useNSKeyedUnarchiver
: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:You are calling
-retain
and then using the accessor which is specified ascopy
, 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.这对我有用:
This works for me: