NSUndoManager 撤消不使用核心数据
我正在尝试创建一个 iPhone 应用程序,用户可以在其中添加条目。当他按下新条目时,会弹出一个框,询问他一些信息。然后他可以按“取消”或“保存”来放弃数据或将其保存到磁盘。
为了保存,我使用了 Core Data 框架,它运行得很好。但是,我无法使用“取消”按钮。当弹出窗口询问信息时,我在托管对象上下文 (MOC) 中创建一个新对象。然后,当用户按下取消时,我尝试使用属于 MOC 的 NSUndoManager。
我还想使用嵌套撤消组来执行此操作,因为可能存在嵌套组。
为了测试这一点,我编写了一个简单的应用程序。该应用程序只是启用了核心数据的“基于窗口的应用程序”模板。对于核心数据模型,我创建了一个名为“Entity”且具有整数属性“x”的实体。然后在 applicationDidFinishLaunching 中,我添加以下代码:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
unsigned int x=arc4random()%1000;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager beginUndoGrouping];
NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
NSLog(@"Insert Value %d",x);
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager endUndoGrouping];
[self.managedObjectContext.undoManager undoNestedGroup];
NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityEntity];
NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
for(entity in result) {
NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
}
[window makeKeyAndVisible];
}
这个想法很简单。尝试插入一个新的实体对象,撤消它,获取 MOC 中的所有实体对象并将它们打印出来。如果一切正常,最后应该不会有任何物体。
但是,我得到以下输出:
[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136
如您所见,在我尝试撤消其创建后,该对象出现在 MOC 中。 关于我做错了什么有什么建议吗?
I am trying to create an iPhone application where the user can add entries. When he presses a new entry, a box will popup asking him for some information. Then he can either press "Cancel" or "Save" to discard the data or save it to disk.
For saving, I am using the Core Data framework, which works pretty well. However, I cannot get the "Cancel" button to work. When the window pops up, asking for information, I create a new object in the managed object context (MOC). Then when the user presses cancel, I try to use the NSUndoManager belonging to the MOC.
I would also like to do it using nested undo groups, because there might be nested groups.
To test this, I wrote a simple application. The application is just the "Window based application" template with Core Data enabled. For the Core Data model, I create a single entity called "Entity" with integer attribute "x". Then inside the applicationDidFinishLaunching, I add this code:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
unsigned int x=arc4random()%1000;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager beginUndoGrouping];
NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
NSLog(@"Insert Value %d",x);
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager endUndoGrouping];
[self.managedObjectContext.undoManager undoNestedGroup];
NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityEntity];
NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
for(entity in result) {
NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
}
[window makeKeyAndVisible];
}
The idea is simple. Try to insert a new Entity object, undo it, fetch all Entity objects in the MOC and print them out. If everything worked correctly, there should be no objects at the end.
However, I get this output:
[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136
As you can see, the object is present in the MOC after I try to undo its creation.
Any suggestions as to what I am doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的问题是由于以下事实引起的:与 OS X 不同,iPhone 托管对象上下文默认不包含撤消管理器。您需要明确添加一个。
将应用程序委托中的 ManagedObjectContext 属性生成的代码更改为如下所示:
进行更改后,不再打印第二条日志消息。
希望有帮助...
戴夫
Your problem is caused by the fact that, unlike OS X, the iPhone managed object context does not contain an undo manager by default. You need to explicitly add one.
Change the generated code in the app delegate for the managedObjectContext property to look like this:
After making that change, the 2nd log message is no longer printed.
Hope that helps...
Dave
我尝试过戴夫的方法,但对我不起作用。
我终于在Apple的示例中找到了解决方案 CoreDataBooks
诀窍是创建一个与您应用程序上下文共享协调器的新上下文。要放弃更改,您不需要做任何事情,只需放弃新的上下文对象即可。由于您共享协调器,因此保存会更新您的主要上下文。
这是我的改编版本,其中我使用静态对象作为临时上下文来创建新的 ChannelMO 对象。
我希望它能帮助
贡索
I tried Dave approach, but did not work for me.
I finally found the solution in Apple's example CoreDataBooks
The trick is to create a new context that shares the coordinator with you App's context. To discard the changes you dont need to do a thing, just discard the new context object. Since you share the coordinator, saving updates your main context.
Here is my adapted version, where I use a static object for the temp context to create a new ChannelMO object.
I hope it helps
Gonso
它应该有效。您是否正确地将撤消管理器分配给了 ManagedObjectContext?如果您的操作正确,默认情况下会启用撤消注册,您应该可以开始操作了。 此处有一篇关于核心数据的好文章。 这里有一个关于核心数据和 NSUndoManager 的很好的教程。希望有帮助。
It should work. Did you correctly assign the undo manager to your managedObjectContext? If you have rightly done that, it by default has undo registration enabled, and you should be good to go. There is a good article on core data here. There is a good tutorial on core data and NSUndoManager here. Hope that helps.