首先说明 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
这样的函数了。