2014-09-05 3 views
1

Я хотел бы распечатать данные, хранящиеся в объектах Core Data, в коде в инструкции NSLog.Как вы печатаете объекты Core Data?

Фоновая информация: Я читаю данные из PList для предпопуляции, а затем передаю их в Core Data. Выпущенное приложение будет читать только из Core Data.

Вот что мой Plist выглядит следующим образом:

Recipes.plist

Вот мой график объект:

object graph

Вот мой код:

-(void)initXML 
{ 
    [self deleteAllEntities:@"Recipes"]; 

    [self copyXMLtoEntities]; 

    [self printEntities]; 
} 

_

// deletes data from all entities to ready them for pre-population 
-(void)deleteAllEntities:(NSString *)entityDescription 
{ 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    NSError *error; 
    NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; 

    for (NSManagedObject *managedObject in items) 
    { 
     [self.managedObjectContext deleteObject:managedObject]; 
     DLog(@"%@ ..object deleted", entityDescription); 
    } 

    if (![self.managedObjectContext save:&error]) 
    { 
     DLog(@"Error deleting %@ - error:%@", entityDescription, error); 
    } 
} 

_

// This copies data from the PList to Core Data Entities, aka pre-population 
-(void)copyXMLtoEntities 
{   
    NSDictionary *allRecipesDictionary = [self getRecipes]; 
    DLog(@"allRecipes: [%@]", allRecipesDictionary); 

    Recipes *recpies = [NSEntityDescription insertNewObjectForEntityForName:@"Recipes" inManagedObjectContext:self.managedObjectContext]; 

    for (NSString *recipeKey in allRecipesDictionary) 
    { 
     NSDictionary *recipeDict = [allRecipesDictionary objectForKey:recipeKey]; 

     Recipe *recipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:self.managedObjectContext]; 
     recipe.id = recipeKey; 
     recipe.name = [recipeDict objectForKey:@"name"]; 

     NSMutableArray *contentItemsArray = [[NSMutableArray alloc] init];    

     NSArray *contentArrayToIterate = [recipeDict objectForKey:@"content"];    

     // loop through content array and add each item 
     for (int i=0 ; i < [contentArrayToIterate count] ; i++) 
     { 
      // create text or image content items 
      // add them to the array 
      // create entities and add them to contentItemsArray 

      NSDictionary *contentItemDict = contentArrayToIterate[i]; 

      NSDictionary *textItemDict = [contentItemDict objectForKey:@"textItem"]; 
      NSDictionary *imageItemDict = [contentItemDict objectForKey:@"imageItem"]; 
      NSString *sequenceStr = [contentItemDict objectForKey:@"sequence"]; 

      if (textItemDict != nil) 
      { 
       NSString *text = [textItemDict objectForKey:@"text"]; 
       TextItem *textItem = [NSEntityDescription insertNewObjectForEntityForName:@"TextItem" inManagedObjectContext:self.managedObjectContext]; 

       textItem.text = text; 
       textItem.sequence = sequenceStr; 

       // add entity to the array 
       [contentItemsArray addObject:textItem]; 
      } 

      if (imageItemDict != nil) 
      { 
       NSString *filename = [imageItemDict objectForKey:@"filename"]; 

       ImageItem *imageItem = [NSEntityDescription insertNewObjectForEntityForName:@"ImageItem" inManagedObjectContext:self.managedObjectContext]; 

       imageItem.filename = filename; 
       imageItem.sequence = sequenceStr; 

       // add entity to the array 
       [contentItemsArray addObject:imageItem]; 
      } 
     } // loop through content 

     recipe.contentItems = [NSSet setWithArray:contentItemsArray]; 
     [recpies addRecipeObject:recipe]; 
    } // loop through recipes 

    [self saveContext]; 
} 

_

// This returns the Dictionary of Recipes 
-(NSDictionary *)getRecipes 
{ 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Recipes" ofType:@"plist"]; 
    NSDictionary *plist = [[NSDictionary alloc] initWithContentsOfFile:path]; 

    // recipes 
    NSDictionary *recipes = [plist objectForKey:@"Recipes"]; 

    return recipes; 
} 

_

Печать словаря, как это:

DLog(@"allRecipes: [%@]", allRecipesDictionary); 

дает мне хорошо категоризированный выход так:

allRecipes: [{ 
    "BLUEBERRY_PIE_001" =  { 
     content =   (
          { 
           textItem =     { 
            sequence = 1; 
            text = "Mix sugar, cornstarch, salt, and cinnamon, and sprinkle over blueberries."; 
           }; 
          }, 
          { 
           imageItem =     { 
            filename = "mixIngredients.jpg"; 
            sequence = 2; 
           }; 
          }, 
           ... 

Печать из основных данных Сущности либо как это:

DLog(@"self.recipes: [%@]", self.recipes); 

или это:

DLog(@"| self.recipes description: [%@]", [self.recipes description]); 

дает мне это:

self.recipes: [(
"<Recipes: 0x9951840> (entity: Recipes; id: 0x9962730 <x-coredata://4E308A08-FB8A-44C5-887A-88C335378A14/Recipes/p2> ; data: {\n recipe =  (\n );\n})" 

)]

Как я могу заставить его выглядеть как распечатка словаря? Прямым образом, о котором я могу думать, является добавление метода «печати» к каждому объекту, который выполняет итерации по своим собственным наборам. У меня 32 объекта в моем полном приложении. Я хотел бы избежать необходимости писать этот код каждый раз, когда я создаю новые объекты из графа объектов.

Более эффективным способом было бы сканировать атрибуты каждого объекта и перебирать их. Эта ссылка показывает, как это сделать для атрибутов, но не для отношений: http://iphonedevelopment.blogspot.com/2010/08/core-data-odds-and-ends.html

Как вы делаете эту работу для отношений?

ответ

1

Самый простой способ

for (Recipe *r in recipesObject.recipe) { NSLog(@"%@", r); } 

вы получите некоторые дополнительные не так довольно выходных данных ядра, но если это для информации или отладки, она должна быть тонкой. Кроме того, отношения могут быть не полностью зарегистрированы.

Лучше, создайте способ, например prettyDescription, в котором вы форматируете вывод по своему вкусу. Вы можете поместить это в подкласс NSManagedObject или (лучше) его расширение.

-(NSString*)prettyDescription { 
    NSMutableString *result = [NSMutableString new]; 
    [result appendString:self.name]; 
    [result appendString:@"\n"]; 
    for (ContentItem *item in self.contentItems) { 
     // append details from item to the result 
    } 
    return [NSString stringWithString:result]; // return immutable string 
} 

Теперь вы можете войти все рецепты с

for (Recipe *r in recipesObject.recipe) { NSLog(@"%@", r.prettyDescription); } 

NB: Я думаю, вы должны переименовать объекты и атрибуты для наглядности следующим образом:

Recipes   --> RecipesCollection 
Recipes.recipe --> RecipesCollection.recipes 
Recipe.recipes --> Recipe.collection 
+1

Спасибо для вашего ответа, и я ценю ваши предлагаемые соглашения о переименовании. –

+1

Это похоже на чистый способ сделать это. Тем не менее, у меня есть много классов сущностей в моем полном объектном графе (всего 32, это всего лишь примерная часть), и для создания отдельного описания для каждого класса потребуется большая работа. Кроме того, всякий раз, когда я вношу изменения в графы объектов и автоматически создаю классы сущностей, мне придется снова добавить код. Есть ли способ создать prettyDescription в NSManagedObject, который наследуется и печатает все свойства для любого типа сущности? –

+0

Я бы подумал, что можно отвлечь его, но, конечно же, не без усилий. Прагматичной альтернативой было бы использовать «описание» и просто добавить «описания» отношений вручную. – Mundi

Смежные вопросы