当模型放在静态库中时,executeFetchRequest返回类型已更改

时间:2011-02-13 16:39:57

标签: objective-c ios core-data ios4 static-libraries

我希望对于拥有比我更多的核心数据和XCode经验的人来说,这将是一件轻松的事。

我正在尝试将iOS应用的模型层移动到静态库,以便我可以重复使用它。我已成功分离代码并构建/运行应用程序。不幸的是,我遇到了一个特殊的问题。

请考虑以下代码段:

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 个答案:

答案 0 :(得分:0)

根据您设置Core Data堆栈的方式,在其内容中,检查当您读取NSManagedObjectModel时,通常从NSBundle实例化您有一些有效实体。在模型返回的项目中设置断点,然后在调试器调用中设置:

po [[managedObjectModel entitiesByName] allKeys]

如果返回实体列表,那么我不确定究竟发生了什么,但是,我怀疑它会返回一个空列表,因为代码无法在项目中找到任何妈妈文件。

这是我为了解决这个问题而采取的措施。在静态库项目中(或者如果静态库只是主项目中的另一个目标),请创建一个新的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堆栈中使用它。

如果人们想要的话,我想我可以在某个地方发布这个来源。无论如何,希望能让你走上正轨。