Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将复杂对象写入文件objective-c_Objective C_Serialization - Fatal编程技术网

将复杂对象写入文件objective-c

将复杂对象写入文件objective-c,objective-c,serialization,Objective C,Serialization,我发现很难写入/读取自定义对象数组。在我的应用程序中,Contact类将NSDictionary作为属性,此字典将数组作为键的对象。 我使用NSCoder和NSKeyedArchiever序列化/反序列化我的对象,甚至尝试了NSPropertyList序列化。我总是在序列化NSDictionary时出错。这是我的代码,对于如何序列化具有复杂结构的自定义对象,我并没有找到一个通用的答案 //Contact.m //phoneNumbers is a NSDictionary #pragma mar

我发现很难写入/读取自定义对象数组。在我的应用程序中,Contact类将NSDictionary作为属性,此字典将数组作为键的对象。 我使用NSCoder和NSKeyedArchiever序列化/反序列化我的对象,甚至尝试了NSPropertyList序列化。我总是在序列化NSDictionary时出错。这是我的代码,对于如何序列化具有复杂结构的自定义对象,我并没有找到一个通用的答案

//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:

  • 实现一个触发编码的实例方法(幸运的是,我可以在这里分享这个方法^\uuuu^):

  • 拥有
    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

  • 为了支持自动编码,imp
    NSKeyedUnarchiver *unarc = [[NSKeyedUnarchiver alloc] initForReadingWithData:[NSData dataWithContentsOfFile:dataFilePath]];
    MyCoolFileDataStore *data = [unarc decodeObject];
    [unarc release];
    return data;