使用Core Data时的模型实例化问题
我对核心数据的一方面有点困惑。 也就是说,我什么时候使用基本的 alloc/init 例程 vs 创建一个具有核心数据的对象并将其保存到当前的托管对象上下文中。
我知道这是一个相当模糊的问题,所以让我举个例子。
我目前正在开发一个应用程序,它会迭代 iPhone 上用户的所有通讯录。 从那里,我编写了一个名为“Person”的模型类。 我曾经在人员循环中做这样的事情:
Person *person = [[Person alloc] initWithWrapper:mywrapper];
mywrapper 将包含一个带有 person 属性的 NSDictionary。 稍后我就可以使用 person 对象填充我的应用程序中的地址簿。
现在我开始使用核心数据重建应用程序的部分内容。 我是否继续使用上述策略来填充我的地址簿? 或者我应该这样做:
Person *person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
[person setName:name];
[person setDob:dob];
// Commit the change.
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
问题是,每次应用程序启动时都会执行此代码。 我是否应该不使用核心数据,因为每次应用程序加载时它都会用人员的冗余实例填充存储机制? 我应该修改我的 NSManagedObject (Person 类)并添加我的 initWithWrapper: 方法并像平常一样继续吗?
有点困惑,希望澄清。
I'm slightly confused in one aspect of Core Data. That is, when do I use the rudimentary alloc/init routine vs created an object with core data and saving it into the current managed object context.
I know that's a rather vague question, so let me give you an example.
I have an application I'm currently working on that iterates through all of a user's contact book on the iPhone. From there, I wrote a model class called 'Person'. I used to do something like this in a loop of people:
Person *person = [[Person alloc] initWithWrapper:mywrapper];
mywrapper would contain an NSDictionary with the attributes for person. Later I'd be able to populate the address book in my app with the person objects.
Now I've started rebuilding parts of the app with Core Data. Do I continue using the strategy above to populate my address book? Or do I do something like this instead:
Person *person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
[person setName:name];
[person setDob:dob];
// Commit the change.
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
The problem is, this code gets executed everytime the app gets started. Should I not be using core data as it will populate the storage mechanism with redundant instances of person everytime the app loads? Should I modify my NSManagedObject (Person class) and add my initWithWrapper: method and continue as I normally would there?
Slightly confused, would love clarification.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您永远不应该在托管对象上下文之外初始化 Core Data 对象 - 这根本没有意义。 拥有一些对
您没有任何好处,因为如果没有上下文(以及模型和存储协调器)的支持,您将无法保存对象、操作它或真正执行 Core Data 提供的任何有用的操作。
当您第一次将对象插入 Core Data 时,您应该仅使用
alloc
-init
组合; 这就是initWithEntity:insertIntoManagedObjectContext:
方法的用途。 你是对的,每次调用该方法时,你都会将一个新对象插入到 Core Data 上下文中并因此进行存储,如果你不小心,你可能会得到重复的对象。如果您在每次启动时运行代码,我会建议您提出一个核心数据查询,该查询返回一些现有的 Person 对象集,并且仅添加不存在的对象(使用初始化方法)商店中已经存在。 如果该对象已存在,请修改它而不是创建新对象。
诀窍是让这样的东西正常执行。 您不应该为 iPhone 地址簿中的每个联系人执行核心数据提取; 许多像这样的小件物品都非常昂贵。 理论上,您可以获取两个 NSSet - 一个 Person 对象,一个联系人 - 然后通过某个唯一键(例如联系人名字和姓氏的哈希值)对它们进行比较。 我把优化留给你。
关键点是:不要在 Core Data 对象上使用
alloc
和init
除非您打算第一次将该对象插入上下文< /强>。 相反,请查看现有对象并在必要时修改它们。You should never be initializing Core Data objects outside of a managed object context - there's simply no point. Having some
does you no good since you can't save the object, manipulate it, or really do anything useful that Core Data provides without the context (and thus model and store coordinator) backing it up.
You should instead only use the
alloc
-init
combo when you are inserting an object into Core Data for the first time; this is what theinitWithEntity:insertIntoManagedObjectContext:
method is for. And you're right, every time you call that method you are inserting a new object into the Core Data context and therefore store, and you may wind up with duplicate objects if you're not careful.What I would instead recommend for you, if you're running code on every startup, is to come up with a Core Data query that returns some set of existing Person objects, and only add objects (using the initialization method) that don't already exist in the store. If the object already exists, modify it instead of creating a new one.
The trick is getting something like this to perform properly. You shouldn't do a Core Data fetch for every contact in the iPhone address book; many small fetches like this are very expensive. You could in theory get two NSSets - one of Person objects, and one of contacts - then compare them by some unique key (like a hash of the first and last names of the contact). I leave the optimization to you.
The key point is this: don't use
alloc
andinit
on a Core Data object unless you mean to insert that object for the first time into a context. Instead look at your existing objects and modify them if necessary.是的,最简单的方法是将 initWithWrapper 方法添加到 Person 类中。 它会是这样的:
唯一的缺点是这个方法必须知道它应该将对象插入到哪个 ManagedObjectContext 中,所以你必须找到一种方法来提供它。
话虽这么说,我自己一直在使用这种模式。
Yeah, it's simplest to add the initWithWrapper method to your Person class. It would be something like this:
The only downside to this is that this method has to know which managedObjectContext it should insert the object into, so you have to figure out a way to provide that.
That being said, I use this pattern myself all the time.