我正在尝试合并两个NSDictionaries:

NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *combinedAttributes = [areaAttributes mutableCopy];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];

但是出现以下错误:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: 'The key 'latitude' is not defined for this NSKnownKeysDictionary'
latitudegpsAttributes中的键

最佳答案

这里的问题是您不是在处理普通字典,而是在使用NSKnownKeysDictionary,这是Apple在Cocoa的各个部分中使用的未记录类型。

如果从SDK中转储ObjC类信息-或者,如果听起来太吓人,请阅读someone else's version-您会发现这实际上是NSMutableDictionary的子类,而不仅仅是NSDictionary,因此它已经可变,因此不需要mutableCopy

更重要的是,如果您阅读了 NSCopying NSMutableCopying 协议(protocol)的定义方式,那么没有什么要求mutableCopy返回与它的基类可兼容的东西了。只是它是可变的,并且与其基类具有不变的兼容性。真烦人。

答案是生成一个新的可变字典,并将 key 从两个NSKnownKeysDictionary对象复制到该字典中:

NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];
NSMutableDictionary *combinedAttributes = [NSMutableDictionary dictionaryWithCapacity:20];
[combinedAttributes addEntriesFromDictionary:areaAttributes];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];

(显然,如果您担心性能,则可以调整20,或者从每个字典中获取键的数量并传递总数。但是通常,这无关紧要。)

您可能想知道苹果为什么要这么做。但是,如果您考虑一下,这是一件方便的事情。在某些库的内部,您有一个可以像C struct一样使用的对象,但在外部看起来像NSDictionary。 (类似于Python中的namedtuple的目的。)返回它们的方法都旨在返回NSDictionary,而不是NSMutableDictionary,因此没有人会知道它们的键集受到限制。当然,除非他们调用mutableCopy

您可能还想知道如何提前知道这一点。好吧,你真的不能。记录对象的类型,编写异常处理程序并记录异常,或者让其崩溃并在崩溃转储中找到该异常。或者,您也可以采取防御措施,并假设任何词典都可以给您一个无用的mutableCopy,然后将其浅拷贝到您控制的类型的词典中。

关于ios - 合并NSDictionaries-NSUnknownKeyException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14331715/

10-11 14:56