iphone, Сохранение данных во многих отношениях, Базовые данные - PullRequest
0 голосов
/ 26 ноября 2010

Я работаю над небольшим приложением для iphone с использованием Core Data, где я получил сущности Person и Image. Отношения между Человеком и Имиджем есть для многих. Один человек для многих изображений.

Проблема возникает при сохранении метода. Во время сохранения мне сначала нужно «ДОБАВИТЬ» несколько данных изображения, которые я получил из ImagePickerViewController, в Person, а затем «СОХРАНИТЬ» сущность Person в реальную БД. ((в том же методе))

if (managedObjectContext == nil)
{
managedObjectContext = [(CoreDataCombine01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
//???: how to init _PersonImage?
_PersonImage = (PersonImage *)[NSEntityDescription insertNewObjectForEntityForName:@"PersonImage" inManagedObjectContext:managedObjectContext];     
//_PersonImage = [_PersonImage init];
//_PersonImage = [[_PersonImage alloc] init];
_PersonImage.originalImage = imageData;

managedObjectContext = nil;
[managedObjectContext release];

.

 if (managedObjectContext == nil)
  {
  managedObjectContext = [(CoreDataCombine01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext]; 
[person addPersonToPersonImageObject:_PersonImage];//runTime error 
[_PersonImage release];

.

NSError *error = nil;
if (![person.managedObjectContext save:&error]) {
    // Handle error
    NSLog(@"Unresolved error at save %@, %@", error, [error userInfo]);
    exit(-1);  // Fail
}

тогда я получил ошибку, сказав:

"-[NSConcreteMutableData CGImage]: unrecognized selector sent to instance" 

и

 "*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableData CGImage]: unrecognized selector sent to instance".

Я догадался, что ошибка произошла из двойного использования NSEntityDescription из одного managedObjectContext . Поэтому я просто инициализирую класс Person, который автоматически получается из модели данных и импортируется вручную, как закомментированная строка, а не с помощью managedObjectContext.

Это не дает никакой ошибки, но выдает ошибку времени выполнения, когда я нажимаю кнопку сохранения.

Когда я использовал отношения один-к-одному, не было проблем с сохранением, поэтому я думаю, что использование managedObjectContext для Person - правильный путь. Однако, как только я использую отношение ко многим, мне нужно сохранить данные изображения в объекте PersonImage. И сущность должна быть так или иначе инициализирована.

Чего мне не хватает?

Ответы [ 2 ]

4 голосов
/ 26 ноября 2010

Хорошо.

Я посмотрел код, который вы разместили на GitHub, и обнаружил несколько проблем с вашим контроллером DetailView, которые я обрисовал ниже.

Во-первых, вы былинеправильная передача контекста управляемого объекта в подробный вид, что означает, что когда вы пытались сохранить ваши объекты, не было контекста, из которого они были бы сохранены.Считайте контекст управляемого объекта «черновиком» вашего постоянного хранилища.Любые изменения, внесенные вами в NSManagedObject, будут отслеживаться и сохраняться в вашем контексте до тех пор, пока вы не сохраните их с помощью команды [managedObjectContext save].

Итак, чтобы было ясно, вы создаете свой контекст в своем AppDelegate, а затем вы передаетессылка на него в вашем RootViewController с rootViewController.managedObjectContext = self.managedObjectContext

Из RootViewController вам нужно передать управляемый объектObjectContext в DetailView, используя ту же технику.Итак, в вашем методе tableView:didSelectRowAtIndexPath: вы должны передать ссылку на контекст, чтобы любые изменения, сделанные вами в этом представлении, были отслежены и в конечном итоге могли быть сохранены:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
     DetailView *detailView = [[DetailView alloc] initWithNibName:@"DetailView" bundle:nil];
     detailView.event = (Event *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
     detailView.managedObjectContext = self.managedObjectContext;

     // ...
     [self.navigationController pushViewController:detailView animated:YES];
     [detailView release];
}

Я также обновил все остальныессылки на managedObjectContext, где вы создавали экземпляр нового объекта контекста, чтобы просто указать на self.managedObjectContext, то есть:

JustString *_justString = [NSEntityDescription insertNewObjectForEntityForName:@"JustString" inManagedObjectContext:self.managedObjectContext];

Как только это вышло, есть только одна вещь, которая мешает вам сохранитьобъект изображения, который TechZen затронул выше.

В вашем контроллере DetailView у вас есть метод imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{, в котором вы преобразуете UIImage в NSData, а затем назначаете его своему экземпляру сущности Image.

Проблема в том, что в вашей объектной модели (см. Event.m) у вас уже есть метод преобразователя с именем -(id)transformedValue:(id)value.

Таким образом, вы пытались преобразовать UIImage в NSData.и затем передача NSData объекту, который фактически ожидал UIImage.В этом случае я бы рекомендовал, чтобы ваша объектная модель имела дело с преобразованием данных, поэтому в вашем контроллере DetailView закомментируйте код преобразователя UIImage to NSData и передайте изображение непосредственно в ваш управляемый объект:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    UIImage *selectedImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    // Transform the image to NSData
    // ImageToDataTransformer *transformer = [[[ImageToDataTransformer alloc] init] autorelease];
    // NSData *imageData = [transformer transformedValue:selectedImage];
    Image *_image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:self.managedObjectContext];    
    _image.justImage = selectedImage;
    [event addEventToImageObject:_image];
    [picker dismissModalViewControllerAnimated:YES];
}

После этого вам следует идти вперед, поэтому попробуйте и дайте нам знать, если это решит ваши проблемы.

CoreData может иметь немного крутой кривой обучения, но как только вы ее получитевы поймете, что это один из самых красивых API-интерфейсов, доступных в разработке для iOS.

Удачи вам в этом и дайте нам знать, как у вас дела!Рог

1 голос
/ 28 ноября 2010

Полученное вами сообщение об ошибке вызвано тем, что вы путаете экземпляр NSData с экземпляром UIImage.

Как и NSString, NSArray и аналогичные базовые классы, NSData представляет собой кластер классов вместо одного класса. NSConcreteMutableData является одним из классов в кластере.

Ваша проблема возникает из-за того, что вы пытаетесь отправить сообщение CGImage в экземпляр NSData, который, конечно, не имеет метода CGImage.

Поскольку для сохранения изображения в атрибуте Core Data необходимо использовать преобразователь значения, я бы посоветовал взглянуть на преобразователь значения и / или метод назначения изображения.

Глядя на ваш код, я подозреваю, что у вас установлен Person.originalImage как трансформируемый атрибут, но вы пытаетесь присвоить ему объект NSData. Когда преобразователь значения пытается преобразовать экземпляр NSData, думая, что это UIImage, он генерирует ошибку.

...