将复杂对象写入文件objective-c
我发现很难写入/读取自定义对象数组。在我的应用程序中,Contact类将NSDictionary作为属性,此字典将数组作为键的对象。 我使用NSCoder和NSKeyedArchiever序列化/反序列化我的对象,甚至尝试了NSPropertyList序列化。我总是在序列化NSDictionary时出错。这是我的代码,对于如何序列化具有复杂结构的自定义对象,我并没有找到一个通用的答案将复杂对象写入文件objective-c,objective-c,serialization,Objective C,Serialization,我发现很难写入/读取自定义对象数组。在我的应用程序中,Contact类将NSDictionary作为属性,此字典将数组作为键的对象。 我使用NSCoder和NSKeyedArchiever序列化/反序列化我的对象,甚至尝试了NSPropertyList序列化。我总是在序列化NSDictionary时出错。这是我的代码,对于如何序列化具有复杂结构的自定义对象,我并没有找到一个通用的答案 //Contact.m //phoneNumbers is a NSDictionary #pragma mar
//Contact.m
//phoneNumbers is a NSDictionary
#pragma mark Encoding/Decoding
-(void)encodeWithCoder:(NSCoder *)aCoder
{
NSLog(@"Encoding");
[aCoder encodeObject:self.firstName forKey:@"firstName"];
NSLog(@"First name encoded");
[aCoder encodeObject:self.lastName forKey:@"lastName"];
NSLog(@"Last name encoded");
[aCoder encodeInt:self.age forKey:@"age"];
NSLog(@"Age encoded");
NSString *errorStr;
NSData *dataRep = [NSPropertyListSerialization dataFromPropertyList:self.phoneNumbers
format:NSPropertyListXMLFormat_v1_0
errorDescription:&errorStr];
NSLog(@"Data class %@", [dataRep class]);
if(!dataRep)
{
NSLog(@"Error encoding %@", errorStr);
}
[aCoder encodeObject:dataRep forKey:@"phones"];
NSLog(@"Encoding finished");
}
- (id) initWithCoder: (NSCoder *)coder
{
if (self = [super init])
{
[self setFirstName:[coder decodeObjectForKey:@"firstName"]];
[self setLastName:[coder decodeObjectForKey:@"lastName"]];
[self setAge:[coder decodeIntForKey:@"age"]];
NSString *errorStr;
NSData *data=[coder decodeObjectForKey:@"phones"];
NSDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:&errorStr];
if(!propertyList)
{
NSLog(@"Error %@", errorStr);
}
[self setPhoneNumbers:propertyList];
}
return self;
}
//Serializing/Deserializing an array of Contact objects:
#pragma mark Import/Export
//Export Contacts to file
-(void)exportContactsToFile
{
BOOL done=[NSKeyedArchiver archiveRootObject:self.contacts toFile:[PathUtility getFilePath:@"phonebook"]];
NSLog(@"Export done: %i", done);
}
//Import Contacts from file
-(void)importContactsFromFile
{
self.contacts = [NSKeyedUnarchiver unarchiveObjectWithFile:[PathUtility getFilePath:@"phonebook"]];
}
在objective-c中有没有一种通用的好方法来序列化/反序列化对象?谢谢
我得到的错误是:
0objc_msgSend
1 CF_保留
...
这是堆栈跟踪,但我没有发现其他错误(您不需要对self.phoneNumber使用
NSPropertyListSerialization
。NSDictionary遵循NSCoding
协议
所以,[aCoder encodeObject:self.phoneNumbers forKey:@“phones”];
应该足够了
只要一个类遵守NSCoding(几乎所有苹果提供的类都遵守NSCoding),您可以只使用
-encodeObject:forKey:
,因为该方法将调用该对象的-encodeWithCoder:
实现。您不需要对self.phoneNumber使用NSPropertyListSerialization
。NSDictionary遵循NSCoding
协议
所以,[aCoder encodeObject:self.phoneNumbers forKey:@“phones”];
应该足够了
只要一个类遵守NSCoding(几乎所有苹果提供的类都遵守NSCoding),您可以只使用
-encodeObject:forKey:
,因为该方法将调用该对象的-encodeWithCoder:
的实现。我的专有库中有一个特殊类,该类自动读取其属性列表,并使用getter和setter对该对象进行编码和解码。很抱歉,我无法在此处共享代码但我至少可以一步一步地告诉你我的课程是如何运作的:
NSCoding
和NSCopying
协议+(void)initialize
内部,使用class\u copyPropertyList()
、property\u getName()
和property\u copyAttributeList()
迭代类的属性定义。有关这些函数的详细信息,请参阅strncmp(attribute.name,“T”,1)==0
(是的,其中是一个c字符串)的属性。使用该属性值确定属性的类型。例如,“i”表示int
,“i”表示无符号int
,如果它以“{”开头然后它是一个struct
等。请参阅NSDictionary
中。在属性迭代结束时,使用类名作为键将此字典存储在静态和全局NSMutableDictionary
中-(void)encodeWithCoder:(NSCoder*)aCoder
来迭代属性名称类型对,调用属性getter方法(通常是-(returnType)propertyName
),并使用适当的encodeType:
方法在编码器内部对其进行编码(例如,encodeInt:
,encodeFloat:
,encodeObject:
,encodeCGPoint:
等)-(id)initWithCoder:(NSCoder*)aDecoder
要迭代属性名称类型对,请使用适当的decodeTypeForKey:
方法从解码器对其进行解码(例如,decodeintfookey:
,decodeFloatForKey:
,decodeObjectForKey:
,decodeCGPointForKey:
等)并调用属性设置器方法(通常-(void)setPropertyName:
)NSData
后,您可以使用它执行任何操作,例如调用writeToFile:atomicly:
甚至[[NSUserDefaults standardUserDefaults]setObject:[self-wrapinsdata]forKey:key]
NSKeyedUnarchiver *unarc = [[NSKeyedUnarchiver alloc] initForReadingWithData:[NSData dataWithContentsOfFile:dataFilePath]];
MyCoolFileDataStore *data = [unarc decodeObject];
[unarc release];
return data;
抱歉,这有点冗长,但就我而言,创建这个类所花费的额外麻烦确实节省了很多时间。今天努力,明天轻松;)我的专有库中有一个特殊的类,它可以自动读取其属性列表,并使用getter和setter对对象进行编码和解码。很抱歉,我无法在此处共享代码,但我至少可以逐步向您介绍我的类的工作原理:
NSCoding
和NSCopying
协议+(void)initialize
内部,使用class\u copyPropertyList()
、property\u getName()
和property\u copyAttributeList()
迭代类的属性定义。有关这些函数的详细信息,请参阅strncmp(attribute.name,“T”,1)==0
(是的,其中是一个c字符串)的属性。使用该属性值确定属性的类型。例如,“i”表示int
,“i”表示无符号int
,如果它以“{”开头然后它是一个struct
等。请参阅NSDictionary
中。在属性迭代结束时,使用类名作为键将此字典存储在静态和全局NSMutableDictionary
中NSKeyedUnarchiver *unarc = [[NSKeyedUnarchiver alloc] initForReadingWithData:[NSData dataWithContentsOfFile:dataFilePath]];
MyCoolFileDataStore *data = [unarc decodeObject];
[unarc release];
return data;