有没有办法实例化 NSManagedObject 而不插入它?

发布于 2024-09-26 13:48:05 字数 586 浏览 9 评论 0原文

我有一个用于插入事务的用户界面。一旦用户单击加号,他就会看到屏幕,我想实例化我的 Core Data NSManagedObject 实体,让用户可以对其进行操作。然后,当用户单击“保存”按钮时,我将调用保存函数。

所以具体到代码:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
//even if i dont call save: its going to show up on my table
[self.managedObjectContext save:&error]

PS 我在该表上使用 NSFetchedResultsController ,我看到 NSFetchedResultsController 正在向表中插入一个部分和一个对象。

我的想法是,如果有一种方法可以实例化 Transaction NSManagedObject,我可以更新它而无需保存,直到客户端选择这样做。

I have a user interface to insert a Transaction. once the user clicks on a plus he gets the screen and i want to instantiate my Core Data NSManagedObject entity let the user work on it. Then when the user clicks on the Save button i will call the save function.

so down to code:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
//even if i dont call save: its going to show up on my table
[self.managedObjectContext save:&error]

P.S i am using an NSFetchedResultsController on that table and I see that the NSFetchedResultsController is inserting a section and an object to the table.

My thought is if there is a way to instantiate the Transaction NSManagedObject i could update it with out saving untill the client choses to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我最亲爱的 2024-10-03 13:48:05

无论如何,Marcus Zarra 似乎在推广nil 上下文方法,声称创建新上下文的成本很高。有关更多详细信息,请参阅此答案类似的问题。

更新

我目前正在使用零上下文方法,并且遇到了其他人可能感兴趣的内容。要创建没有上下文的托管对象,请使用 NSManagedObjectinitWithEntity:insertIntoManagedObjectContext: 方法。根据Apple对此方法的文档:

如果context不为nil,则此方法
调用 [context insertObject:self]
(这会导致awakeFromInsert
调用)。

这里的含义很重要。创建托管对象时使用 nil 上下文将阻止调用 insertObject:,从而阻止调用 awakeFromInsert。因此,使用 nil 上下文时,在 awakeFromInsert 中完成的任何对象初始化或默认属性值设置都不会自动发生。

底线:当使用没有上下文的托管对象时,awakeFromInsert 不会被自动调用,您可能需要额外的代码来补偿。

For what it's worth, Marcus Zarra seems to be promoting the nil context approach, claiming that it's expensive to create a new context. For more details, see this answer to a similar question.

Update

I'm currently using the nil context approach and have encountered something that might be of interest to others. To create a managed object without a context, you use the initWithEntity:insertIntoManagedObjectContext: method of NSManagedObject. According to Apple's documentation for this method:

If context is not nil, this method
invokes [context insertObject:self]
(which causes awakeFromInsert to be
invoked).

The implication here is important. Using a nil context when creating a managed object will prevent insertObject: from being called and therefore prevent awakeFromInsert from being called. Consequently, any object initialization or setting of default property values done in awakeFromInsert will not happen automatically when using a nil context.

Bottom line: When using a managed object without a context, awakeFromInsert will not be called automatically and you may need extra code to compensate.

纸伞微斜 2024-10-03 13:48:05

使用 nil MOC 存在一个基本问题:不同 MOC 中的对象不应该互相引用——这可能也适用于关系的一侧具有 nil MOC 的情况。如果保存会发生什么? (当你的应用程序的另一部分保存时会发生什么?)

如果你的对象没有关系,那么你可以做很多事情(比如 NSCoding)。

您也许可以在 NSPredicate 中使用 -[NSManagedObject isInserted] (大概在插入和成功保存之间为 YES)。或者,您可以使用具有相同行为的瞬态属性(在 awakeFromInsert 中将其设置为 YES,在 willSave 中将其设置为 NO)。如果应用程序的不同部分保存,这两种情况都可能会出现问题。

不过,使用第二个 MOC 是 CoreData “应该”使用的方式;它会自动为您处理冲突检测和解决。当然,您不想每次发生更改时都创建一个新的 MOC;如果您不介意 UI 的某些部分看到其他部分中未保存的更改(MOC 间通信的开销可以忽略不计),那么使用一个 MOC 来处理缓慢的“用户线程”未保存的更改可能是明智的。

There's a fundamental problem with using a nil MOC: Objects in different MOCs aren't supposed to reference each other — this presumably also applies when one side of a relationship has a nil MOC. What happens if you save? (What happens when another part of your app saves?)

If your object doesn't have relationships, then there are plenty of things you can do (like NSCoding).

You might be able to use -[NSManagedObject isInserted] in NSPredicate (presumably it's YES between inserting and successfully saving). Alternatively, you can use a transient property with the same behaviour (set it to YES in awakeFromInsert and NO in willSave). Both of these may be problematic if a different part of your app saves.

Using a second MOC is how CoreData is "supposed" to be used, though; it handles conflict detection and resolution for you automatically. Of course, you don't want to create a new MOC each time there's a change; it might be vaguely sensible to have one MOC for unsaved changes by the slow "user thread" if you don't mind some parts of the UI seeing unsaved changes in other parts (the overhead of inter-MOC communication is negligible).

同展鸳鸯锦 2024-10-03 13:48:05

这是我的解决方法:

在加载时,我们知道我们正在处理一项新事务,我创建了一个脱离上下文的事务。

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
        transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

然后,当谈到建立关系时,我这样做了:

if( transaction.managedObjectContext == nil){
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext];
        Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
        category.title = ((Category *)obj).title;
        transaction.category = category;
        [category release];
    }
    else {
        transaction.category = (Category *)obj;
    }

最后保存:

if (transaction.managedObjectContext == nil) {
        [self.managedObjectContext insertObject:transaction.category];
        [self.managedObjectContext insertObject:transaction];
    }
    //NSLog(@"\n saving transaction\n%@", self.transaction);

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

here is how i worked it out:

On load, where we know we are dealing with a new transaction, i created an out of context one.

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
        transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

then when it came to establishing a relation ship i did this:

if( transaction.managedObjectContext == nil){
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext];
        Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
        category.title = ((Category *)obj).title;
        transaction.category = category;
        [category release];
    }
    else {
        transaction.category = (Category *)obj;
    }

and at the end to save:

if (transaction.managedObjectContext == nil) {
        [self.managedObjectContext insertObject:transaction.category];
        [self.managedObjectContext insertObject:transaction];
    }
    //NSLog(@"\n saving transaction\n%@", self.transaction);

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
眼睛会笑 2024-10-03 13:48:05

您可以使用 -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] 插入 NSManagedObjectContext,并为托管对象上下文传递 nil。当然,您必须将其分配给上下文(在保存之前使用 -[NSManageObjectContext insertObject:] 。据我所知,这实际上并不是 Core Data 中的预期模式(但是请参阅@mzarra的回答此处)。棘手的排序问题(即确保实例在预期拥有上下文之前被分配给上下文,等等)。 ,保存上下文,并处理 NSManagedObjectDidSaveNotification 将更改合并到您的“主”上下文中。如果用户取消事务,您只需清除上下文并继续您的业务。

You can insert an NSManagedObjectContext with the -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:], passing nil for the managed object context. You must, of course, assign it to a context (using -[NSManageObjectContext insertObject:] before saving. This is, as far as I know, not really the intended pattern in Core Data, however (but see @mzarra's answer here). There are some tricky ordering issues (i.e. making sure the instance gets assigned to a context before it expects to have one, etc.). The more standard pattern is to create a new managed object context and insert your new object into that context. When the user saves, save the context, and handle the NSManagedObjectDidSaveNotification to merge the changes into your 'main' context. If the user cancels the transaction, you just blow away the context and go on with your business.

无人问我粥可暖 2024-10-03 13:48:05

可以使用 nil 作为上下文来创建 NSManagedObject,但如果有其他 NSManagedObject,它必须链接到它会导致错误。我这样做的方式是将上下文传递到目标屏幕并在该屏幕中创建一个 NSManagedObject。使所有更改链接其他 NSManagedObjects。如果用户点击取消按钮,我会删除 NSManagedObject 并保存上下文。如果用户点击保存按钮,我会更新 NSManagedObject 中的数据,将其保存到上下文中,然后释放屏幕。在源屏幕中,我通过重新加载更新表。

删除目标屏幕中的 NSManagedObject 可以为核心数据提供更新文件的时间。这通常足以让您看不到表视图中的变化。在 iPhone 日历应用程序中,从保存时间到显示在表格视图中的时间存在延迟。从 UI 的角度来看,这可以被认为是一件好事,因为您的用户将专注于刚刚添加的行。我希望这有帮助。

An NSManagedObject can be created using the nil as the context, but if there other NSManagedObjects it must link to it will result in an error. The way I do it I pass the context into the destination screen and create a NSManagedObject in that screen. Make all the changes link other NSManagedObjects. If the user taps the cancel button I delete the NSManagedObject and save the context. If the user taps the the save button I update the data in the NSManagedObject, save it to the context, and release the screen. In the source screen I update the table with a reload.

Deleting the NSManagedObject in the destination screen gives core data time to update the file. This is usually enough time for you not to see the change in the tableview. In the iPhone Calendar app you have a delay from the time it saves to the time it shows up in the tableview. This could be considered a good thing from a UI stand point that your user will focus on the row that was just added. I hope this helps.

失与倦" 2024-10-03 13:48:05
transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil];

如果最后一个参数为 nil,它将返回一个 NSManagedObject 而不保存到数据库

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil];

if the last param is nil, it will return a NSManagedObject without save to db

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文