我有一个从 NSObject 继承的名为 XYZ 的类和一个包含 XYZ 对象的数组。我需要将此数组写入到文档目录的 plist 文件中。尝试 [array writeToFile....] 后,我发现 writeToFile 失败,因为该数组包含 XYZ 类的自定义对象。
可能的解决方案是将对象转换为 NSData。实现这一目标的不同方法是什么?我发现NSCoding是合适的,但无法理解如何使用它。任何帮助将不胜感激。
我有一个从 NSObject 继承的名为 XYZ 的类和一个包含 XYZ 对象的数组。我需要将此数组写入到文档目录的 plist 文件中。尝试 [array writeToFile....] 后,我发现 writeToFile 失败,因为该数组包含 XYZ 类的自定义对象。
可能的解决方案是将对象转换为 NSData。实现这一目标的不同方法是什么?我发现NSCoding是合适的,但无法理解如何使用它。任何帮助将不胜感激。
Ray Wenderlich 的博客上有一个非常好的教程,它解释了如何使用 NSCoding。
只需在对象中实现 *-(void)encodeWithCoder:(NSCoder )encode和 *-(id)initWithCoder:(NSCoder )decoder方法,这些方法尊重 NSCoding 协议,如下所示:
// Header
@interface AnObject: NSObject <NSCoding>
// Implementation
- (void) encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:ivar1 forKey:@"ivar1"];
[encoder encodeFloat:ivar2 forKey:@"ivar2"];
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:coder];
ivar1 = [[coder decodeObjectForKey:@"ivar1"] retain];
ivar2 = [[coder decodeObjectForKey:@"ivar2"] retain];
return self;
}
您也可以在此处查看官方文档。
在实现encodeWithCoder:
和initWithCoder:
自定义类之后,这里是如何编写和读取:
写:
NSError *error;
NSData* archiveData = [NSKeyedArchiver archivedDataWithRootObject:yourClassInstance];
[archiveData writeToFile:filePath options:NSDataWritingAtomic error:&error];
读:
NSData *archiveData = [NSData dataWithContentsOfFile:filePath];
YourClass *yourClassInstance = (NSArray*)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
使您的 XYZ 类符合NSCoding协议确实非常适合您尝试做的事情。为此,请将 NSCoding 协议添加到类的接口声明中:
@interface XYZ <NSCoding>
然后,您需要在您的实现中实现 encodeWithCoder: 和 initWithCoder:。“使用编码器编码”意味着“获取对象的当前状态,并将其打包到一个称为“编码器”的通用对象中”。“Init with coder”的意思是“给定一个已经打包好的编码器对象,用打包到编码器中的数据来配置自己”。在这两种方法中,“编码器”都是NSCoder的一个实例,它有一个相当简单的接口用于编码(“打包”)和解码(“解包”)基本类型。
这是一个示例实现:
@implementation XYZ
- (id)initWithCoder:(NSCoder*)encoder
{
self = [self init];
if (self)
{
self.myIntProperty = [encoder decodeIntForKey:@"myInt"];
}
return self;
}
– (void)encodeWithCoder:(NSCoder*)decoder
{
[decoder encodeInt:self.myIntProperty forKey:@"myInt"];
}
@end
您需要实现两种方法:-initWithCoder:
和-encodeWithCoder:
. 阅读NSCoding
文档;它们是非常直接的方法。您基本上想使用与其名称对应的键对实例变量进行编码/解码。
这很简单。对于给定的类Foo
:
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSCoding> {
NSArray* bar_;
NSUInteger baz_;
}
@property (nonatomic, retain) NSArray *bar;
@property (nonatomic, assign) NSUInteger baz;
@end
为了符合协议,你所要做的NSCoding
就是实现initWithCoder:
anddecodeWithCoder
消息:
#import "Foo.h"
@implementation Foo
@synthesize bar = bar_;
@synthesize baz = baz_;
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.bar forKey:@"bar"];
[encoder encodeInteger:self.baz forKey:@"baz"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if ((self = [super init])) {
self.bar = [decoder decodeObjectForKey:@"bar"];
self.baz = [decoder decodeIntegerForKey:@"baz"];
}
return self;
}
- (void) dealloc {
[bar_ release];
[super dealloc];
}
@end