核心数据获取一对多实体

时间:2014-04-08 05:03:14

标签: ios objective-c core-data nspredicate

问题:

由于未捕获的异常'NSInvalidArgumentException'而终止应用程序时出错,原因是:'to-many key not here here'。

我想获取Section和News实体中的所有属性。但这些属性应该相互匹配。例如,假设我有一个部分名称=“yy”,其匹配的新闻是title =“sports”和title =“每日新闻”。另一个部分名称=“aa”,只有一个匹配的新闻标题是title =“Horoscopes”等等...获取正确的部分属性及其正确的新闻属性(一个或多个)。

  1. 以下是核心数据结构:
  2. enter image description here

    1. 我有实体类的新闻和部分:(自动生成)

      //News.h:
      @class Section;
      @interface News : NSManagedObject
      
      @property (nonatomic, retain) NSNumber * id;
      @property (nonatomic, retain) NSString * updated;
      @property (nonatomic, retain) NSString * title;
      @property (nonatomic, retain) NSString * synopsis;
      @property (nonatomic, retain) NSString * pub_date;
      @property (nonatomic, retain) NSNumber * imageId;
      @property (nonatomic, retain) Section *sectionRelation;
      @end
      
      // News.m define those attribute as @dynamic
      
      // Section.h 
      @class News;
      @interface Section : NSManagedObject
      
      @property (nonatomic, retain) NSString * name;
      @property (nonatomic, retain) NSSet *newsRelation;
      @end
      
      @interface Section (CoreDataGeneratedAccessors)
      - (void)addNewsRelationObject:(News *)value;
      - (void)removeNewsRelationObject:(News *)value;
      - (void)addNewsRelation:(NSSet *)values;
      - (void)removeNewsRelation:(NSSet *)values;
      
      // section.m still @dynamic
      
    2. 我使用NSDictionary将值插入这些实体:

      -(Section*)insertSectionEntity:(NSDictionary*)values
      {
         Section* sectionObject = [NSEntityDescription     insertNewObjectForEntityForName:ENTITY_NEWS_SECTION inManagedObjectContext:[[CoreDataHelper  coreDataManager]managedObjectContext]];
         [sectionObject setValuesForKeysWithDictionary:values];
         // I did not use [section addNewsRelationObject:news]; I used in somewhere else.
         return sectionObject;
       }
      
       -(News*)insertNewsEntity:(NSDictionary*)values
      {
         News* newsObject = [NSEntityDescription insertNewObjectForEntityForName:ENTITY_NEWS inManagedObjectContext:[[CoreDataHelper coreDataManager]managedObjectContext]];
         [newsObject setValuesForKeysWithDictionary:values];
         return newsObject;
       }
      
    3. 以下是将两个实体存储到核心数据中的方式:

      // this array include the NSDictionary values of Section and News entity
      -(void)storeNewsAndSectionEntity:(NSMutableArray*)array
      {
         if(array.count!=0){
            News* news       = NULL;
            Section* section = NULL;
      
           // break into two different dictionaries and store in core data
           for (NSDictionary* dic in array) {
              // name is the attribute of section
              if([dic valueForKey:@"name"]!=nil){
                  section = [self insertSectionEntity:dic];
               }
               else{
                  news = [self insertNewsEntity:dic];
                  [section addNewsRelationObject:news]; // generate relation
               }
            }
            [[CoreDataHelper coreDataManager]saveContext]; // save context
          }
      }
      
    4. 以下是我获取所有实体属性的方法:

      -(NSArray*)fetchCoreDataNews:(Section*)section
      {
          if([[CoreDataHelper coreDataManager]isEntityExist:@"News"]){
      
           // fectch news in relation with that specific section
           NSArray* newsArray = [[CoreDataHelper coreDataManager]fectchEntityBaseOnPredicate:@"News" withPredicate:@"SUBQUERY(sectionRelation, $x, $x.newsRelation == %@).@count != 0" withObject:section];        
           return newsArray;
          }
          else
           return nil;
       }
      
      -(NSArray*)fetchCoreDataSection
      {
         if([[CoreDataHelper coreDataManager]isEntityExist:@"Section"]){
             NSArray* sectionArray = [[CoreDataHelper coreDataManager]fectchAllAttributesFromEntity:@"Section"];
             return sectionArray;
         }
         else
           return nil;
      }
      
       // I think this causing the problem:  Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'to-many key not allowed here'
       -(NSArray*)fectchEntityBaseOnPredicate:(NSString*)entityName withPredicate: (NSString*)predicateString withObject:(id)ManagedObject
       {
      
         NSManagedObjectContext *managedObjectContent = [[CoreDataHelper coreDataManager] managedObjectContext];
         NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
         NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContent];
      
         NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString, ManagedObject];
         [fetchRequest setPredicate:predicate];
         [fetchRequest setEntity:entity];
         NSArray* fectechedElements = [managedObjectContent executeFetchRequest:fetchRequest error:nil]; // SELECT
         return fectechedElements;
        }
      
    5. 谢谢!

1 个答案:

答案 0 :(得分:0)

实际上,我们可以通过使用ValueForKey轻松获得一对多的属性。

// get section entity
_sectionArray = [[[CoreDataControl initCoreDataControl]fetchCoreDataSection]mutableCopy];

// call relation name of each section
NSSet *news = [[_sectionArray objectAtIndex:0] valueForKey:@"newsRelation"];    

// get all related news entities in the parents entity
NSArray* allObjects = [news allObjects];

// then you can call each specific attribute in that entity
[[allObjects objectAtIndex:0]valueForKey:@"title"]; // it will return the attribute.... :)