iPhone,以一对多关系保存数据,核心数据
我正在使用 Core Data 开发一个小型 iphone 应用程序,其中我有一个 Person 和一个 Image 实体。 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".
我猜这个错误来自于重复使用一个 ManagedObjectContext 中的 NSEntityDescription。所以我只是初始化 Person 类,它从数据模型自动派生并手动导入,就像注释行一样,而不是使用 ManagedObjectContext。
它没有给出任何错误,但当我点击保存按钮时给出运行时错误。
当我使用一对一关系时,保存没有问题,所以我想对 Person 使用 ManagedObjectContext 是正确的方法。但是,一旦我使用一对多关系,我需要将图像数据保存到 PersonImage 实体。并且实体必须以某种方式初始化。
我缺少什么?
I'm working on a small iphone app using Core Data, where I got a Person and an Image entities. The relationship between Person and Image is to-many. One person to many images.
Problem happens at save method. During saving first I need 'ADD' more than one image data, that I got from ImagePickerViewController, to Person and then 'SAVE' the Person entity to actual DB. ((in the same method))
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
}
then I got error saying:
"-[NSConcreteMutableData CGImage]: unrecognized selector sent to instance"
and:
"*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableData CGImage]: unrecognized selector sent to instance".
I guessed the error came from double use of NSEntityDescription from one managedObjectContext. So I just init Person class, that derived automatically from data model and manually imported, like the commented line instead of using managedObjectContext.
It doesn't give any error but give me runtime error when I hit my save button.
When I was using one-to-one relationship there was no problem with saving so I guess using managedObjectContext for Person is right way. However, once I use to-many relationship I need save Image data to PersonImage entity. And the entity has to be initialized in a way or another.
What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧。
我查看了您在 GitHub 上发布的代码,发现 DetailView 控制器存在一些问题,我将在下面概述这些问题。
首先,您没有正确地将托管对象上下文传递到详细视图,这意味着当您尝试保存对象时,没有可供保存的上下文。将托管对象上下文视为持久存储的“草稿”。您对 NSManagedObject 所做的任何更改都将被跟踪并保留在您的上下文中,直到您使用
[managedObjectContext save]
命令将其保留为止。因此,需要明确的是,您正在 AppDelegate 中创建上下文,然后使用
rootViewController. ManagedObjectContext = self.managedObjectContext
将对其的引用传递给 RootViewController从 RootViewController 中,您需要传递 ManagedObjectContext使用相同的技术深入到 DetailView。因此,在您的
tableView:didSelectRowAtIndexPath:
方法中,您应该传递对上下文的引用,以便您对该视图所做的任何更改都将被跟踪并最终可以保留:我还更新了所有其他引用到 ManagedObjectContext,您在其中实例化一个新的上下文对象以简单地指向 self.managedObjectContext,即:
一旦解决了这个问题,就只剩下一件事情会阻止您正确保存图像对象,TechZen 上面提到了这一点。
在 DetailView 控制器中,您有一个 imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 方法,您可以将 UIImage 转换为 NSData,然后将其分配给您的 Image 实体实例。
问题是您的对象模型中已经有一个名为
-(id)transformedValue:(id)value
的转换器方法(请参阅 Event.m)。所以基本上你试图将 UIImage 转换为 NSData,然后将 NSData 传递给实体,该实体实际上需要 UIImage。在这种情况下,我建议您让对象模型处理数据转换,因此在 DetailView 控制器中,注释掉 UIImage 到 NSData 转换器代码,并将图像直接传递给您的托管对象:
之后,您应该很好,请尝试一下,如果它解决了您的问题,请告诉我们。
CoreData 的学习曲线可能有点陡峭,但一旦您“掌握”了它,您就会意识到它是 iOS 开发中制作最精美的 API 之一。
祝你好运,让我们知道你进展如何!
罗格
Alright.
I've had a look at the code you posted on GitHub and found a few issues with your DetailView controller, which I am outlining below.
Firstly, you were not passing your managed object context to the detail view properly, meaning that when you were trying to save your objects there was no context for them to be saved from. Think of the Managed Object Context as a "draft" of your persistent store. Any changes you make to an NSManagedObject will be tracked and kept on your context until you persist them with the
[managedObjectContext save]
command.So just to be clear, you are creating your context in your AppDelegate, then you passed a reference to it to your RootViewController with
rootViewController.managedObjectContext = self.managedObjectContext
From the RootViewController, you need to pass the managedObjectContext down to the DetailView using the same technique. So in your
tableView:didSelectRowAtIndexPath:
method, you should pass a reference to the context so any changes you make on that view will be tracked and can eventually be persisted:I've also updated all the other references to managedObjectContext where you were instantiating a new context object to simply point to self.managedObjectContext,i.e:
Once that's out of the way, there is only one more thing that was preventing you from saving the image object properly, which TechZen touched on above.
In your DetailView controller, you have a
imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
method where you transform the UIImage into NSData and then assign it to your Image entity instance.The problem with that is that you already have a transformer method in your object model (see Event.m) called
-(id)transformedValue:(id)value
.So basically you were trying to transform the UIImage into NSData and then passing NSData to the entity, which was actually expecting an UIImage. In this case, I'd recommend that you let your object model deal with the data transformation so in your DetailView controller, comment out the UIImage to NSData transformer code, and pass the image directly to your managed object:
After that, you should be good to go so give it a try and let us know if it solves your problems.
CoreData can have a bit of a steep learning curve but once you 'get it' you will realise it's one of the most beautifully crafted APIs available in iOS development.
Good luck with it and let us know how you go!
Rog
您收到的错误消息是由于您将 NSData 实例与 UIImage 实例混淆而引起的。
与 NSString、NSArray 和类似的核心类一样,NSData 是一个类簇而不是单个类。 NSConcreteMutableData 是集群中的类之一。
出现问题是因为您尝试将消息 CGImage 发送到 NSData 实例,该实例当然没有 CGImage 方法。
由于您必须使用值转换器将图像存储在核心数据属性中,因此我建议您查看值转换器和/或分配图像的方法。
查看您的代码,我怀疑您将 Person.originalImage 设置为可转换属性,但您尝试为其分配 NSData 对象。当值转换器尝试转换 NSData 实例并认为它是 UIImage 时,它会生成错误。
The error message you are getting is caused by you confusing an NSData instance for an UIImage instance.
Like NSString, NSArray and similar core classes, NSData is a class cluster instead of single class. NSConcreteMutableData is one of the classes in the cluster.
Your problem arises because you are trying to send the message
CGImage
to an NSData instance which of course does not have aCGImage
method.Since you have to use a value transformer to store an image in a Core Data attribute, I would suggest looking at you value transformer and/or the method where you assign the image.
Looking at your code, I suspect you have the
Person.originalImage
set as a transformable attribute but you attempt to assign an NSData object to it. When the value transformer attempts to transform the NSData instance while thinking it is UIImage, it generates the error.