如何根据另一个实体的多对多关系访问Core Data实体?

时间:2012-04-11 16:16:10

标签: objective-c ios core-data one-to-many nsfetchrequest

我正在使用示例库存应用学习CoreData。我的数据模型有2个实体,“占有”和“资产类型”。财产与资产类型的关系称为“assetType”,资产类型与名为“财产”的财产有很多关系。每个Possession只有一个资产类型,但资产类型有很多财产。

我想根据资产类型将表格视图分类。我需要一些帮助来填充我的数据结构。

以下是我将如何建模我的表视图控制器

表格部分的NSArray 数组中的每个section对象都是一个带有2个键的NSDictionary,@“Header” - 它是资产类型,@“Possessions”是该资产类型的一系列所有物。

我可以处理从这个结构构建我的表视图没问题。我还可以处理从CoreData获取资产类型到我的字典的标题键。我感到难过的是如何利用资产类型所拥有的多对多关系,这样我就可以将所有物品放入字典数组中。

如何将每个资产类型的所有权归入阵列?

我是否需要使用谓词创建获取请求以获取具有匹配资产类型的所有权,或者是否有更简单的方法? - 似乎效率低下,因为它必须检查所有财产的比赛!?!?!?!?

AssetType实体的to-many关系“所有权”是AssetType实体的可访问属性吗?如果是这样,我如何访问它?它返回了什么?

我不是在寻找免费代码,但如果需要,我愿意发布我的代码。我真正喜欢的是知道解决这个问题的最佳方法,并可能在线指向有用的信息来实现这一目标。我不是一个完整的新手,但我仍然无法绕过CoreData,到目前为止,Apple文档在这个问题上仍然让我很困惑。我很感谢你提供的任何帮助。

2 个答案:

答案 0 :(得分:1)

如果您使用Xcode默认NSManagedObject模板创建了AssetType类(请参阅图像)

File/New/File.../Core Dats/NSManagedObject subclass

你应该在AssetType.h中有类似的东西:

@interface AssetType : NSManagedObject

@property (nonatomic, retain) NSSet *possessions;

@end

@interface AssetType (CoreDataGeneratedAccessors)

- (void) addPossessionsObject:    (Possession *) value;
- (void) removePossessionsObject: (Possession *) value;
- (void) addPossessions:          (NSSet *) value;
- (void) removePossessions:       (NSSet *) value

@end

因此,如果您有AssetType对象,则可以通过possessions属性访问与其相关的所有Possession对象。默认情况下,它不是按顺序排序的,因此要将这些对象作为数组访问,您需要调用集合的-allObjects方法,该方法将集合中的对象作为数组返回,然后可能以某种方式对这些对象进行排序。

编辑:

此外,即使您没有以这种方式创建NSManagedObject子类并且它还没有实现possessions属性,您也可以按照上面示例中所述的相同方式将此属性添加到类中并在AssetType.m中将其实现为@dynamic possessions

答案 1 :(得分:0)

从我正在阅读的内容中我怀疑这比你想象的容易得多。

听起来像你设想使用字典数据结构在你的UITableController的tableView:cellForRowAtIndexPath:方法中使用,当你可能根本不需要使用它时。

当Table视图控制器实例化时,(viewDidLoad:可能是最合适的位置)只需使用以下代码检索您的资产:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Asset" inManagedObjectContext:context];
[fetchRequest setEntity:entity];

NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
    // handle errors here
}

[fetchRequest release];

如果需要,将fetchedObjects数组赋值给NSArray类型的实例变量,以便在管理表的UITableViewController类的多个位置引用它。然后在上面的代码之后你可以这样做:

self.assets = fetchedObjects;

如果您尚未为资产NSManagedObject创建自定义子类,则数组中的每个对象都将是NSManagedObject类型,您需要将其读入该类型的变量中。

当您需要与资产相关的所有物清单时,它已存在于您阵列中的每个资产对象中(这就是CoreData的美妙之处,如果它实际上没有在内存中实例化,那么您尝试访问该属性时, CoreData将为您自动实例化它。)

因此,假设您没有为NSManagedObject定义自定义类,那么您的数组对象将属于该类型。将数组中的一个资产对象分配给名为(适当)资产的本地变量

例如,这会将索引0处的对象分配给局部变量。

NSManagedObject *asset = [self.assets objectAtIndex:0];

你可以用代码获得你的一套财产:

NSSet *assetPossessions = [asset valueForKey:"@possessions"];

(假设xCode中模型编辑器中定义的关系已命名为“所有者”)

或者,如果您为Asset NSManagedObject生成了自己的自定义子类,那么这可能是一个更好的示例:

MyManagedAssetObject *asset = [self.assets objectAtIndex:0];
NSSet *assetPossessions = asset.possessions;

请注意,在此示例中,我假设您没有使用NSFetchedResultsController。实际上使用一个表来管理表实际上更容易,但是通常情况下,编程只有在您知道“只需要一件事”之后才会更容易,因此(矛盾地)会使答案变得复杂。既然你没有提到它,我假设你没有使用它。

希望这会有所帮助。保罗