Как сохранить массив NSManagedObjects в NSManagedObject - PullRequest
1 голос
/ 04 января 2011

Я загружаю свое приложение со списком свойств данных с веб-сайта.Этот файл списка свойств содержит NSArray из NSDictionaries, который сам содержит NSArray из NSDictionaries.В основном, я пытаюсь загрузить tableView категорий меню ресторана, каждая из которых содержит пункты меню.

Мой файл списка свойств в порядке.Я могу загрузить файл и пройтись по структуре узлов, создавая описания NSEntityDescription, и могу сохранить их в Core Data.Все работает нормально и ожидаемо, за исключением того, что в моем управляемом объекте категории меню у меня есть NSArray пунктов меню для этой категории.Позже, когда я получаю категории, указатели на пункты меню в категории теряются, и я получаю все пункты меню.Предполагаю ли я использовать предикаты или Core Data отслеживает мой граф объектов для меня?

Может кто-нибудь взглянуть на то, как я загружаю Core Data, и указать на ошибку в моей логике?Я довольно хорош как с SQL, так и с ООП, но ORM немного сбивает с толку.Я думал, что я должен просто иметь возможность использовать агрегацию в моих управляемых объектах и ​​что инфраструктура будет отслеживать указатели для меня, но, очевидно, нет.

 NSError *error;
 NSURL *url = [NSURL URLWithString:@"http://foo.com"];
 NSArray *categories = [[NSArray alloc] initWithContentsOfURL:url];
 NSMutableArray *menuCategories = [[NSMutableArray alloc] init];

 for (int i=0; i<[categories count]; i++){
  MenuCategory *menuCategory = [NSEntityDescription
           insertNewObjectForEntityForName:@"MenuCategory" 
           inManagedObjectContext:[self managedObjectContext]];

  NSDictionary *category = [categories objectAtIndex:i];
  menuCategory.name = [category objectForKey:@"name"];
  NSArray *items = [category objectForKey:@"items"];
  NSMutableArray *menuItems = [[NSMutableArray alloc] init];
  for (int j=0; j<[items count]; j++){
   MenuItem *menuItem = [NSEntityDescription
          insertNewObjectForEntityForName:@"MenuItem" 
          inManagedObjectContext:[self managedObjectContext]];

   NSDictionary *item = [items objectAtIndex:j];
   menuItem.name = [item objectForKey:@"name"];
   menuItem.price = [item objectForKey:@"price"];
   menuItem.image = [item objectForKey:@"image"];
   menuItem.details = [item objectForKey:@"details"];
   [menuItems addObject:menuItem];
  }
  [menuCategory setValue:menuItems forKey:@"menuItems"];
  [menuCategories addObject:menuCategory];
  [menuItems release];
 }

 if (![[self managedObjectContext] save:&error]) {
  NSLog(@"An error occurred: %@", [error localizedDescription]);
 }

Ответы [ 2 ]

0 голосов
/ 21 марта 2015

У меня была такая же проблема. Существуют 2 основные проблемы с использованием NSSet s и Core Data: если вам нужны не отличимые объекты и вам нужно их упорядочить. Например, скажем, у вас есть 2 сущности в Core Data: профессор и студент. Студент берет 10 классов по программе на получение степени, и вы хотите иметь (один-ко-многим) отношения между студентом и профессором для того, чтобы занятия были приняты. Также один и тот же профессор может преподавать более одного класса. Так я преодолел проблему. Создайте атрибут двоичных данных (назовем его profData) в студенческих словарях и сохраните в них словари, которые позволяют восстанавливать данные по мере необходимости. Примечание: не храните массив профессоров, так как они наследуются от NSManagedObject против NSObject. Это может вызвать проблемы. Вы можете найти нужные методы, используя категорию. В этом примере я создал категорию «Студент» под названием ProfList (Student+ProfList.h/m). Это исключает код из подклассов NSManagedObject, поэтому, если мои атрибуты в Базовых данных изменятся, я могу автоматически перегенерировать подклассы, не стирая этот код. Вот пример кода:

// Student+ProfList.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Student.h"
#import "Professor.h"

@interface Student (ProfList)
- (NSArray *)getStudentsFullList;
- (void)storeStudentsFullList:(NSArray *)fullList;
@end

// Student+ProfList.m

#import "Student+ProfList.h"

@implementation Student (ProfList)

- (NSArray *)getStudentsFullList
{
    NSData *storedData = self.profData;
    if (!storedData) return nil;
    NSMutableArray *fullList = [[NSMutableArray alloc] init];

    // Retrieve any existing data
    NSArray *arrayOfDictionaries = [NSKeyedUnarchiver unarchiveObjectWithData:storedData];

    // Get the full professor list to pull from when recreating object array
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Professor"];
    NSSortDescriptor *alphaSort =
    [[NSSortDescriptor alloc] initWithKey:@"name"
                                ascending:YES
                                 selector:@selector(localizedCaseInsensitiveCompare:)];
    [fetchRequest setSortDescriptors:@[alphaSort]];
    NSSet *allProfessors = [NSSet setWithArray:[context executeFetchRequest:fetchRequest error:nil]];
    for (NSDictionary *dict in arrayOfDictionaries) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name LIKE %@", [dict objectForKey:@"name"]];
        NSSet *filteredSet = [allProfessors filteredSetUsingPredicate:predicate];
        Professor *newProfessor = [filteredSet anyObject];
        newProfessor.index = [dict objectForKey:@"index"];
        [fullList addObject:newProfessor];
    }
    return fullList;
}

- (void)storeStudentsFullList:(NSArray *)fullList
{
    NSMutableArray *encodedList = [[NSMutableArray alloc] init];
    for (Professor *professor in fullList) {
        [encodedList addObject:@{@"index" : @([encodedList count]), @"name" : professor.name}];
    }
    NSArray *encodedArray = [NSArray arrayWithArray:encodedList];
    NSData *arrayData = [NSKeyedArchiver archivedDataWithRootObject:encodedArray];
    self.profData = arrayData;
}

#pragma mark - Core Data

- (NSManagedObjectContext *)managedObjectContext
{
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate performSelector:@selector(managedObjectContext)]) {
        context = [delegate managedObjectContext];
    }
    return context;
}

@end

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

0 голосов
/ 04 января 2011

Вы устанавливаете NSArray как объект отношения ко-многим

NSMutableArray *menuItems = [[NSMutableArray alloc] init];
[menuCategory setValue:menuItems forKey:@"menuItems"]; 

, что может вызвать проблемы. (Должно вызвать исключение?) Отношения в CoreData всегда не отсортированы, поэтому NSSets. Добавьте свойство sortIndex к своим объектам для оформления заказа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...