【发布时间】:2009-05-04 11:06:28
【问题描述】:
我有一个 NSMutableArray,它包含 Person (NSString,NSString,int) 类型的对象 我正在寻找一种简单的方法来将此数组保存到光盘并稍后再次加载。
我读了很多关于序列化的文章,但我从来没有这样做过。毕竟这对我来说可能不是最简单的方法。
【问题讨论】:
标签: objective-c arrays serialization
我有一个 NSMutableArray,它包含 Person (NSString,NSString,int) 类型的对象 我正在寻找一种简单的方法来将此数组保存到光盘并稍后再次加载。
我读了很多关于序列化的文章,但我从来没有这样做过。毕竟这对我来说可能不是最简单的方法。
【问题讨论】:
标签: objective-c arrays serialization
第一步是让你的 Person 类实现 NSCoding 协议。基本策略是实现两种方法来序列化和反序列化您希望在会话之间保留的每个对象的实例变量。
#pragma mark NSCoding Protocol
- (void)encodeWithCoder:(NSCoder *)encoder;
{
[encoder encodeObject:[self foo] forKey:@"foo"];
[encoder encodeDouble:[self bar] forKey:@"bar"];
}
- (id)initWithCoder:(NSCoder *)decoder;
{
if ( ![super init] )
return nil;
[self setFoo:[decoder decodeObjectForKey:@"foo"]];
[self setBar:[decoder decodeDoubleForKey:@"bar"]];
return self;
}
要将对象实际写入磁盘,您可以使用 NSArray 的 writeToFile: 方法,或者如果您想更明确地了解它是如何完成的,可以使用 NSKeyedUnarchiver 类。在这两种情况下,如果您想在数据文件中包含其他项目(例如文件格式编号),您还可以将数组放入另一个数据结构(例如字典)中。
【讨论】:
先生。 Charbonneau 的想法是正确的。 NSCoder 抽象了对象的特定序列化,让您只关心需要序列化/反序列化的内容。在-encodeWithCoder:,你可能想要
NSAssert1([encoder allowsKeyedCoding],
@"%@ does not support sequential archiving.",
[self className]);
因为并非所有编码器都支持密钥归档。
在-initWithCoder 中,您应该在初始化对象之前将-initWithCoder:(不仅仅是-init)发送到super:
self = [super initWithCoder:decoder];
if (!self) return nil;
// now use the coder to initialize your state
或者,由于您的对象基本上已经是一个属性列表,您可以添加类似-[Person plistRepresentation]:
- (NSDictionary *)plistRepresentation
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[self firstName], @"firstName",
[self lastName], @"lastName",
[NSNumber numberWithInteger:[self age]], @"age", nil];
}
然后,要序列化Persons 的数组,您可以自己将人员转换为他们的plistRepresentation,然后使用-[NSArray writeToURL:atomically:]。 (当然也可以直接使用NSProperyListSerialization的方法。)
【讨论】:
通过使用 writeToFile:atomically,它在我的代码中不起作用:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *issueURLsPlist = [documentsDirectory stringByAppendingPathComponent:@"test.plist"];
MyClass * myObject = [[MyClass alloc] init];
NSMutableArray * array = [[NSMutableArray alloc] init];
[array addObject:myObject];
[array writeToFile:issueURLsPlist atomically:YES];
MyClass.h
#import <Foundation/Foundation.h>
@interface MyClass : NSObject <NSCoding>
{
}
@property (nonatomic,copy) NSString * foo;
@property (nonatomic) double bar;
@end
MyClass.m
#import "MyClass.h"
@implementation MyClass
- (id)init {
self = [super init];
if (self) {
self.foo = @"test";
self.bar = 0.4f;
}
return self;
}
#pragma mark NSCoding Protocol
- (void)encodeWithCoder:(NSCoder *)encoder;
{
[encoder encodeObject:[self foo] forKey:@"foo"];
[encoder encodeDouble:[self bar] forKey:@"bar"];
}
- (id)initWithCoder:(NSCoder *)decoder;
{
if ( ![super init] )
return nil;
[self setFoo:[decoder decodeObjectForKey:@"foo"]];
[self setBar:[decoder decodeDoubleForKey:@"bar"]];
return self;
}
@synthesize foo;
@synthesize bar;
@end
当我使用带有 NSStrings 的数组时,方法 writeToFile:atomically: 工作正常。
【讨论】: