当模型放置在静态库中时,executeFetchRequest 返回类型发生了变化
Posted
技术标签:
【中文标题】当模型放置在静态库中时,executeFetchRequest 返回类型发生了变化【英文标题】:executeFetchRequest return type changed when model placed in static library 【发布时间】:2011-02-13 16:39:56 【问题描述】:我希望这对于比我有更多 Core Data 和 XCode 经验的人来说是一件容易的事。
我正在尝试将 ios 应用程序的模型层移动到静态库,以便我可以重用它。我已成功分离代码并构建/运行应用程序。不幸的是,我遇到了一个特殊的问题。
考虑以下代码sn-p:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[fetchRequest setEntity:entityDescription];
fetchRequest.includesSubentities = NO;
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"UID = %@", uID]];
fetchArray = [context executeFetchRequest:fetchRequest error:&fetchError];
id obj = [fetchArray objectAtIndex:0];
NSString *fetchArrayIndexZeroEntityName = [[obj entity] name];
当一切都在一个 xcode 项目中时:
根据 xcode 调试器悬停气泡的 obj 指针类型是 MyCustomCoreDataClassName
和
fetchArrayIndexZeroEntityName = @"MyCustomCoreDataClassName"
将核心数据模型移动到静态库后:
根据 xcode 调试器悬停气泡的 obj 指针类型是 NSManagedObject
和
fetchArrayIndexZeroEntityName = @"MyCustomCoreDataClassName"
稍后在我的代码中我进行以下调用:
[obj isKindOfClass:[MyCustomCoreDataClassName class]]
当所有内容都在单个 xcode 项目中时,上述调用返回 YES。 在我将核心数据模型移动到静态库后,上述调用返回 NO。
这种行为显然对我的应用程序产生了相当可怕的后果。对可能出现的问题以及如何解决问题有任何想法吗?完全有可能我将这些项目不完整或不正确地链接在一起,即使它编译时没有错误并且运行至少足以发现上述内容。
谢谢你, 安德鲁
【问题讨论】:
【参考方案1】:根据您设置核心数据堆栈的方式,就在它的内部,检查当您读取通常从 NSBundle 实例化的 NSManagedObjectModel(s) 时,您是否有一些有效的实体。在模型返回的项目中设置断点,然后在调试器调用中:
po [[managedObjectModel entitiesByName] allKeys]
如果返回实体列表,那么我不确定到底发生了什么,但是,我怀疑它会返回一个空列表,因为代码在您的项目中找不到任何 mom 文件。
这是我为解决这个问题所做的。在您的静态库项目中(或者如果您的静态库只是主项目中的另一个目标),创建一个新的 NSBundle 目标。将 Core Data 模型和您拥有的任何映射模型添加到此目标。然后将其作为依赖项添加到您的静态库目标和应用程序目标。在您的主应用程序目标中,将此新包添加到 Copy Bundle Resources 构建阶段。
然后,在您的 Core Data 堆栈中,您只需在所有捆绑包中搜索模型。我的代码有点像这样:
/**
Creates, retains, and returns the managed object model for the application
by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel
if (managedObjectModel) return managedObjectModel;
// Get all the bundles including ones nested inside the main bundle
NSMutableSet *allBundles = [NSMutableSet set];
NSMutableSet *newBundles = [NSMutableSet set];
NSUInteger numberOfBundles = 0;
[allBundles addObject:[NSBundle mainBundle]];
while (numberOfBundles < [allBundles count])
// Look for nested bundles
for(NSBundle *bundle in allBundles)
NSArray *morePaths = [NSBundle pathsForResourcesOfType:@".bundle" inDirectory:[bundle bundlePath]];
if([morePaths count] > 0)
for(NSString *bundlePath in morePaths)
if(![allBundles containsObject:bundlePath])
[newBundles addObject:[NSBundle bundleWithPath:bundlePath]];
// Add the new bundles
[allBundles unionSet:newBundles];
numberOfBundles = [allBundles count];
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:[allBundles allObjects]] retain];
if (managedObjectModel) return managedObjectModel;
return nil;
请注意,上面的代码不需要知道您为模型命名的内容。我在一个单例类中有这个函数,它还实例化持久存储协调器并返回 MOC。如此有效,一旦你完成了,你就可以在任何地方使用 Core Data 堆栈了,你可以在应用程序的任何地方实例化它。
如果人们想要的话,我想我可以在某个地方发布它的来源。无论如何,希望这能让你走上正轨。
【讨论】:
另外 - 该函数中没有任何错误检查,所以,显然它还没有准备好应用程序,因为如果 managedObjectModel 加载失败,什么都不会工作。 查看github.com/blindingskies/BSManagedObjectContextController了解如何执行此操作。以上是关于当模型放置在静态库中时,executeFetchRequest 返回类型发生了变化的主要内容,如果未能解决你的问题,请参考以下文章
当两个成员都在同一个类中时,出现错误“非静态成员引用必须相对于特定对象”