首先说明 ios 中 NSManagedObjectContext 默认的 undoManager是nil的,就是说 undo 和 redo 都是没用的。

但是 rollback函数和reset函数是不设置undoManager对象也能使用的!

看下rollback的说明

Removes everything from the undo stack, discards all insertions and deletions, and restores updated objects to their last committed values.

NSManagedObjectContext的undo和redo都是调用undoManager的undo和redo,在很多情况下,undo一组没有save的操作和rollback整个context是一样的效果---都把context恢复到了上次save后的状态。但是undoManager如果进行了更加复杂的设定,undo就仅仅是恢复一部分数据库操作,而不像rollback那么彻底了!

在 NSManagedObject 的awakeFromInsert函数中找到了以下说明:

If you create a managed object then perform undo operations to bring the managed object context to a state prior to the object’s creation, then perform redo operations to bring the managed object context back to a state after the object’s creation, awakeFromInsert is not invoked a second time.

这里说明了 context中的 undo的一个用处,就是取消一个插入对象!

为了理解 undomanager,贴一段简单的例子:

#import "ViewController.h"

@interface ViewController ()

{

    NSUndoManager *undoManager;
float width;
} @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. undoManager = [[NSUndoManager alloc] init]; width = 1.0; [self setMyWidth:2.0]; if([undoManager canUndo]){
NSLog(@"can undo");
} [undoManager undo]; if([undoManager canUndo]){
NSLog(@"can undo");
} [undoManager redo]; NSLog(@"width is %f",width); } - (void)setMyWidth:(float)newWidth{ if(undoManager.isUndoing){
NSLog(@"is undoing");
} if(undoManager.isRedoing){
NSLog(@"is redoing ");
} float currentWidth = width; if ((newWidth != currentWidth)) {
[[undoManager prepareWithInvocationTarget:self] setMyWidth:currentWidth]; [undoManager setActionName:NSLocalizedString(@"Size Change", @"size undo")]; width = newWidth;
}
} @end

这个例子里的undoManager的操作,coredata都已经实现了,我们不需要写

- (void)setMyWidth:(float)newWidth

这样的函数了。

04-13 11:44