如何序列化包含NSNull的NSDictionary / NSArray / Property List(plist)

时间:2009-08-07 11:22:40

标签: ios objective-c cocoa serialization

我希望使用NSMutableDictionaryNSNull个空值中存储,然后使用属性列表序列化此数据。问题是NSNull是不允许的,我得到“属性列表格式无效”错误。这有解决方法吗?似乎非常令人惊讶的是他们没有将NSNull放在有效的plist对象列表中。

4 个答案:

答案 0 :(得分:14)

在序列化之前,我将NSArray或NSDictionary转换为NSData。以下是nsarray上用于序列化和反序列化的类别。这舒适地处理一些数据是nsnull

@implementation NSArray(Plist)

-(BOOL)writeToPlistFile:(NSString*)filename{
    NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentsDirectory = [paths objectAtIndex:0];
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
    BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES];
    return didWriteSuccessfull;
}

+(NSArray*)readFromPlistFile:(NSString*)filename{
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * documentsDirectory = [paths objectAtIndex:0];
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
    NSData * data = [NSData dataWithContentsOfFile:path];
    return  [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

答案 1 :(得分:9)

请考虑使用NSKeyedArchiver和NSKeyedUnarchiver,而不是使用属性列表。属性列表具有一组固定的类型,并且不包括NSNull,并且不打算进行扩展。

以下是相关文档的链接:NSCodingNSKeyedArchiverNSKeyedUnarchiver

答案 2 :(得分:5)

不,没有办法将NSNull放入属性列表中。 (Trivia:二进制属性列表格式实际上支持空值,但编写器不实现支持。)

对于字典,最简单的解决方法是简单地过滤掉空值,所以{foo =“bar”; baz = null;变成{foo =“bar”; }。

答案 3 :(得分:3)

来自NSPropertyListSerializationClass的文档:

  

属性列表对象。 pl必须   一种NSData,NSString,NSNumber,   NSDate,NSArray或NSDictionary   宾语。容器对象也必须   仅包含这些类型的对象。

所以你需要其中一个。根据数据类型,您可以放置​​占位符而不是NSNull,然后在加载.plist之前/之后执行一个过程(例如,使用零长度NSData对象来表示plist中的NSNull)。究竟什么样的占位符取决于您存储的数据类型,并选择要避免的内容。然后,在加载后,将空NSData转换回NSNull。