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

Ios 如何序列化包含NSNull的NSDictionary/NSArray/Property列表(plist),ios,objective-c,cocoa,serialization,Ios,Objective C,Cocoa,Serialization,我想使用NSNull将一些空值存储在NSMutableDictionary中,然后使用属性列表序列化这些数据。问题是不允许使用NSNull,并且我得到“属性列表格式无效”错误。有解决办法吗?似乎很奇怪,他们没有将NSNull放在有效的plist对象列表中。不,没有办法将NSNull放在属性列表中。(琐事:二进制属性列表格式实际上支持空值,但编写器不实现支持。) 对于字典,最简单的解决方法是简单地过滤掉空值,这样{foo=“bar”baz=null;}就变成了{foo=“bar”;}。来自NSPr

我想使用
NSNull
将一些空值存储在
NSMutableDictionary
中,然后使用属性列表序列化这些数据。问题是不允许使用
NSNull
,并且我得到“属性列表格式无效”错误。有解决办法吗?似乎很奇怪,他们没有将
NSNull
放在有效的plist对象列表中。

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


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

来自NSPropertyListSerializationClass的文档:

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


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

而不是使用属性列表,考虑使用NKEKEDAGEVER和NKEKEDUNCHIVFER。属性列表有一组固定的类型,不包括NSNull,也不打算扩展


以下是相关文档的链接:,和。

在序列化之前,我将NSArray或NSDictionary转换为NSData。以下是nsarray上用于序列化和反序列化的类别。此ComfortabyBy可处理某些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];
}

说真的,苹果的程序员出了什么问题???我讨厌编写这样的代码。DD,如果您想要的是一般序列化,请使用NSCoder。属性列表有一组固定的类型,因此无论扩展到何种程度,都需要转换某些内容。如果您不喜欢属性列表的限制(如文档所示,属性列表不支持NSNull),则不要使用属性列表。正如另一位评论者所建议的,使用您自己的序列化格式。NSPropertyList支持!=序列化。这与我需要空值来表示键存在但没有相应的值(即,我已经知道有一个键没有数据,而不是我不知道的一个新键)并不完全相同。也许你可以将两者序列化a)一个字典,其中只包含具有相应值的键,和B)所有已知密钥的数组,无论它们是否附加了数据。最终,没有办法直接将NSNull放在plist中,所以您需要找到一个解决方法。非常好!这真是太神奇了(我刚刚验证过),但键控archivers中更常见的方法却没有。Saurabh Wadhwa提供的答案非常好,我自己就用过了,可惜原始海报不存在,无法接受。。。