如何保存和加载自定义对象?

通常,我们使用NSKeyedArchiver序列化对象并将其写入文件。
相应地,NSKeyedUnarchiver用于从文件中获取对象。

NSKeyedArchiver的界面是这样的:

  +(BOOL)archiveRootObject:(id)rootObject到File:(NSString *)path; 

NSKeyedArchiver是一个NSCoder。 rootObject应该符合协议NSCoding。

  @协议NSCoding 

-(void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;

@结束

让我们举一个例子:
例如,现在我们有一个customObject:

  @interface CustomObject:NSObject  { 
NSString * mStringValue;
int mIntValue;
BOOL mBOOLValue;
}

@属性(非原子,保留)NSString * stringValue;
@property(非原子,赋值)int intValue;
@property(非原子,分配)BOOL boolValue;

@结束

它符合NSCoding,因此我们需要在.m文件中实现这两种方法

  #define kEncodeKeyStringValue @“ kEncodeKeyStringValue” 
#define kEncodeKeyIntValue @“ kEncodeKeyIntValue”
#define kEncodeKeyBOOLValue @“ kEncodeKeyBOOLValue”

#pragma标记-NSCoding
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.stringValue forKey:kEncodeKeyStringValue];
[aCoder encodeInt:self.intValue forKey:kEncodeKeyIntValue];
[aCoder encodeBool:self.boolValue forKey:kEncodeKeyBOOLValue];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
如果((self = [super init]))
{
self.stringValue = [aDecoder encodeObjectForKey:kEncodeKeyStringValue];
self.intValue = [aDecoder encodeIntForKey:kEncodeKeyIntValue];
self.boolValue = [aDecoder encodeBoolForKey:kEncodeKeyBOOLValue];
}
返回自我
}

现在,我们可以像这样保存和加载customObject:

  -(IBAction)saveObjectPlain:(id)sender { 

printf(“ ======================================= \ n ”);
printf(“ saveObjectPlain ========================== \ n ”);
printf(“ ======================================= \ n ”);

// <创建并保存对象
{
CustomObject * obj = [[[[CustomObject alloc] init] autorelease];
obj.stringValue = @“字符串值”;
obj.intValue = 12345;
obj.boolValue = YES;
[NSKeyedArchiver archiveRootObject:obj toFile:[self tempFilePath]];
printf(“保存: \ n %s \ n ”,[[obj描述] cStringUsingEncoding:NSUTF8StringEncoding]);
}

// <加载并打印对象
{
CustomObject * obj = [NSKeyedUnarchiver unarchiveObjectWithFile:[self tempFilePath]];
printf(“ Load: \ n %s \ n ”,[[obj描述] cStringUsingEncoding:NSUTF8StringEncoding]);
}

printf(“ ======================================= \ n ”);
}

很简单,对吧?

如何保存/加载我们的CustomObjects数组?
由于NSArray符合协议NSCoding,因此非常简单。

  -(IBAction)saveObjectsInArray:(id)sender { 

printf(“ ======================================= \ n ”);
printf(“ saveObjectsInArray ======================= \ n ”);
printf(“ ======================================= \ n ”);

// <创建两个键并保存对象
{
CustomObject * obj1 = [[[[CustomObject alloc] init] autorelease];
obj1.stringValue = @“字符串值1”;
obj1.intValue = 12345;
obj1.boolValue = YES;

CustomObject * obj2 = [[[[CustomObject alloc] init] autorelease];
obj2.stringValue = @“字符串值2”;
obj2.intValue = 54321;
obj2.boolValue = NO;

NSArray * array = [NSArray arrayWithObjects:obj1,obj2,nil];
[NSKeyedArchiver archiveRootObject:array toFile:[self tempFilePath]];

printf(“保存: \ n %s \ n ”,[[数组描述] cStringUsingEncoding:NSUTF8StringEncoding]);
}

// <加载并打印对象
{
NSArray * array = [NSKeyedUnarchiver unarchiveObjectWithFile:[self tempFilePath]];
printf(“ Load: \ n %s \ n ”,[[数组说明] cStringUsingEncoding:NSUTF8StringEncoding]);
}

printf(“ ======================================= \ n ”);
}

因此,如果我们的CustomObject中有一个NSArray类型的成员变量,
我们需要确保数组仅包含符合NSCoding的对象。
否则,将引发无法识别的选择器[.. encodeWithCoder:]的异常。

下一步,如何保存/加载NSDictionary,将CustomObject作为键,将另一个CustomObject作为对象。

这实际上是另一个问题。 我们需要确保CustomObject可以用作NSDictionary中的键。
根据文档,NSDictionary要求其密钥符合协议NSCopying。

  @协议NSCopying 

-(id)copyWithZone:(NSZone *)zone;

@结束

密钥对象需要复制到NSZone描述的指定内存中。
实现就像:

  #pragma标记-NSCopying 
-(id)copyWithZone:(NSZone *)zone {
CustomObject * copy = [[[CustomObject allocWithZone:zone] init];
copy.stringValue = [[[self.stringValue copy] autorelease];
copy.intValue = self.intValue;
copy.boolValue = self.boolValue;
返回副本;
}

我们使用allocWithZone在指定的内存上分配一个CustomObject。
然后将成员变量复制到新实例。

保存/加载过程类似于:

  -(IBAction)saveObjectAsKey:(id)sender { 

printf(“ ======================================= \ n ”);
printf(“ saveObjectAsKey ========================== \ n ”);
printf(“ ======================================= \ n ”);

// <创建两个键并保存对象
{
CustomObject * keyObj = [[[[CustomObject alloc] init] autorelease];
keyObj.stringValue = @“字符串值键”;
keyObj.intValue = 12345;
keyObj.boolValue = YES;

CustomObject * valObj = [[[[CustomObject alloc] init] autorelease];
valObj.stringValue = @“字符串值”;
valObj.intValue = 54321;
valObj.boolValue = NO;

NSDictionary * dict = [NSDictionary dictionaryWithObject:valObj forKey:keyObj];
[NSKeyedArchiver archiveRootObject:dict toFile:[self tempFilePath]];

printf(“保存: \ n %s \ n ”,[[字典说明] cStringUsingEncoding:NSUTF8StringEncoding]);
}

// <加载并打印对象
{
NSDictionary * dict = [NSKeyedUnarchiver unarchiveObjectWithFile:[self tempFilePath]];
printf(“ Load: \ n %s \ n ”,[[dict说明] cStringUsingEncoding:NSUTF8StringEncoding]);
}

printf(“ ======================================= \ n ”);
}

希望能帮助到你! 🙂