如何从上下文中删除未提交的对象?

发布于 2024-10-19 00:34:31 字数 764 浏览 1 评论 0原文

我在应用程序中使用核心数据和 NSFetchedResultsController,为 UIViewTable 提供 Car 对象。我有一个按钮,当用户可以添加新车时,当使用选项卡时,会将应用程序带到另一个视图。我遇到的问题是,即使用户没有在第二个视图中创建汽车,它也会添加到表中。如果我重新启动应用程序,汽车不会添加到数据库中。

这与我在第二个视图中的 viewDidLoad 方法中使用类似以下内容创建 Car 的实例有关:

    car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" 
                                  inManagedObjectContext:context];

即使我不保存上下文,也会添加此实例。

我尝试在第二个视图即将关闭时删除该对象,使用以下方法:

[context deleteObject:car];

这部分有效。汽车未添加到第一页的表中,但看起来数据源的索引已更改。如果我一直向下滚动,我会收到此错误:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFBatchFaultingArray objectAtIndex:]: index (9) beyond bounds (9)'

任何想法将不胜感激。

I'm using core data and NSFetchedResultsController in an app, for feeding a UIViewTable with Car objects. I have a button that, when tabbed, takes the app to another view when the user can add a new Car. The problem I have is that even if the user doesn't create the car in the second view, it's added to the table. If I restart the application, the Car wasn't added to the DB.

This is related to the fact that I create an instance of the Car in the second view, in the viewDidLoad method, using something like this:

    car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" 
                                  inManagedObjectContext:context];

This is added even if I don't save the context.

I tried to delete the object when the second view is about to be closed, using this:

[context deleteObject:car];

This partially works. The car is not added to the table in the first page, but looks like the indexes of the data source are altered. If I scroll all the way down I got this error:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFBatchFaultingArray objectAtIndex:]: index (9) beyond bounds (9)'

Any ideas will be appreciated.

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

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

发布评论

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

评论(2

阳光下慵懒的猫 2024-10-26 00:34:31

尝试通过传递 nil 上下文来创建汽车对象:

car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" 
                              inManagedObjectContext:nil];

从那里,如果用户决定保存它,您可以将该对象移动到主上下文。

另一种选择是为此视图设置一个单独的 MOC(这会增加不必要的复杂性),然后在需要时再次在上下文之间移动对象。

干杯,

Rog

PS:如果您想知道是否可以将 nil 作为 ManagedObjectContext 传递,这直接来自 Apple 关于 NSManagedObject 的文档:

...如果上下文不为零,则此方法
调用 [context insertObject:self]
(这会导致 awakeFromInsert 成为
调用)...

更多详细信息 这里

[编辑]

除此之外,我在查看 NSFetchRequest 文档时发现了一些有趣的东西,并认为您可能想尝试一下(我自己还没有尝试过) 。看来您可以告诉 fetchRequest 在获取对象时是否包含挂起的更改(即不保存):

- (void)setInincludesPendingChanges:(BOOL)yesNo

仅供参考,默认值为 YES - 更多详细信息

Try creating your car object by passing a nil context:

car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" 
                              inManagedObjectContext:nil];

From there, if the user decides to save it you can move the object to the main context.

The other alternative is to have a separate MOC for this view (which adds unnecessary complications) and then again move the object between contexts if/when required.

Cheers,

Rog

PS: if you're wondering whether you can pass nil as the managedObjectContext, this is straight from Apple's docs on NSManagedObject:

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

More details here

[EDIT]

In addition to this, I just came across something interesting when looking at the NSFetchRequest documentation and thought you might want to have a go (I haven't tried myself). It appear that you can tell the fetchRequest whether to include pending changes (i.e. not saved) or not when fetching objects:

- (void)setIncludesPendingChanges:(BOOL)yesNo

FYI the default value is YES - more details here

擦肩而过的背影 2024-10-26 00:34:31

首先,尝试在用户提交更改时延迟新对象的插入。

仅当不合适时:

当上下文发生更改时,NSFetchedResultsController 会自动通知修改其传递给表视图控制器的数据。但是,表视图本身不会被修改,因此您必须自己更新表视图。

这就是为什么 NSFetchedResultsController 有一个委托对象(符合 NSFetchedResultsControllerDelegate 协议),它负责更新表视图。

例如,在 CoreDataBooks 示例项目中,您将在 RootViewController 类中看到此协议的委托方法。最相关的委托方法是controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:。您可能想要执行如下操作:

if (changeType == NSFetchedResultsChangeDelete) {
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];  
}

First, try delaying the insertion of the new object when the user commits the change.

Only if it's not appropriate:

When the context has changed, NSFetchedResultsController is automatically informed to modify its data passed to the table view controller. However, the table view itself is not modified, so you have to update the table view by yourself.

That's why NSFetchedResultsController has a delegate object (conforming to NSFetchedResultsControllerDelegate protocol) which is responsible to update the table view.

For example, in CoreDataBooks sample project, you will see delegate methods of this protocol in RootViewController class. The most related delegate method is controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:. You may probably want to do something like the following:

if (changeType == NSFetchedResultsChangeDelete) {
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];  
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文