当我将-objectForKey发送到 - [NSManagedObjectModel entitiesByName]返回的字典时,-objectForKey:如果传入的键是文字常量,如@“foo”,则返回预期的结果。但是如果我传入一个局部变量,其值被构造为等于@“foo”,则-objectForKey:在Mac OS X 10.9中返回nil。在Mac OS X 10.8中,无论密钥是否为常量,它都会返回预期值。
问题可能是因为在10.9中,-entitiesByName返回一个名为NSKnownKeysDictionary2的NSDictionary的子类。在10.8中,它返回NSKnownKeysDictionary1。我猜是
根据文档-[NSManagedObjectModel entitiesByName] returns an NSDictionary,依次为documented to use -isEquals: to compare keys ...
在字典中,键是唯一的。也就是说,单个字典中没有两个键是相等的(由isEqual确定:)。
所以我认为这是Mac OS X 10.9中的一个错误。我想也许有人没注意到 - [NSManagedObjectModel entitiesByName]在优化它以返回NSKnownKeysDictionary2时是一个公共方法。由于大多数开发人员使用常量字符串作为实体名称,因此这个错误一直在开发人员预览中滑落,没有人注意到。
我错了,还是应该“提交错误”?
谢谢,
杰瑞克里诺克演示此代码的代码(来自我的项目,对不起)如下所示。它来自我个人的NSManagedObject的“超级子类”,它完成了NSManagedObject没有的所有我喜欢的东西。
正如您在代码中的“第一次尝试”中所看到的,方法+ [NSEntityDescription entityForName:inManagedObjectContext:]的结果也受到这个明显错误的影响。
当我运行构建应用程序并在Mac OS X 10.8中运行时,它会记录
但是当我在10.9中使用相同的数据运行相同的构建时,第1次,第2次和第3次尝试显然都失败了,因为它改为记录
代码:
// How I like to name my entities…
+ (NSString*)entityNameForClass:(Class)class {
return [NSStringFromClass(class) stringByAppendingString:@"_entity"] ;
}
+ (NSEntityDescription*)entityDescription {
// Stuff we'll need
NSArray* bundles = [NSArray arrayWithObject:[NSBundle mainBundle]] ;
NSManagedObjectModel* mom = [NSManagedObjectModel mergedModelFromBundles:bundles] ;
NSString* entityName = [self entityNameForClass:self] ; // See above
// What we want
NSEntityDescription* entityDescription = nil ;
// First try.
NSPersistentStoreCoordinator* psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom] ;
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] init] ;
[moc setPersistentStoreCoordinator:psc] ;
entityDescription = [NSEntityDescription entityForName:entityName
inManagedObjectContext:moc] ;
[psc release] ;
[moc release] ;
NSDictionary* entities = [mom entitiesByName] ;
NSLog(@"entities is an %@", [entities className]) ;
NSLog(@"entityName is an %@", [entityName class]) ;
NSLog(@"entities is a dictionary? = %hhd”,
[entities isKindOfClass:[NSDictionary class]]) ;
if (entityDescription) {
NSLog(@"1st try worked for %@", entityName) ;
}
else {
// Second try
entityDescription = [entities objectForKey:entityName] ;
if (!entityDescription) {
// Third try
NSString* entityNameCopy = [entityName copy] ;
entityDescription = [entities objectForKey:entityNameCopy] ;
[entityNameCopy release] ;
}
if (!entityDescription) {
// Fourth try
NSSet* candidateEntityNames = [NSSet setWithObjects:
@"Stark_entity",
@"Ixporter_entity",
nil] ;
for (NSString* candidate in candidateEntityNames) {
if ([entityName isEqualToString:candidate]) {
entityDescription = [entities objectForKey:candidate] ;
if (entityDescription) {
NSLog(@"4th try worked for %@", entityName) ;
break ;
}
}
}
}
}
if (!entityDescription) {
NSLog(@"Internal Error 561-3831 for %@", entityName) ;
}
return entityDescription ;
}