当我们犯错的时候,系统给了我们犯错悔改的机会, 系统提供了让我们回复或者重做的API---NSUndoManager.
NSUndoManager的基本原理是其中有两个栈---取消操作的栈和重做操作的栈,栈里面装的是NSInvocation对象。当执行一些特定操作后,在取消栈中压入NSInvocation,其中封装了消息的消息接受者,方法和参数等。当取消操作时,执行取消栈上栈顶的NSInvocation的消息, 重做的栈里面会压入重做的NSInvocation对象。这样就通过两个栈和NSInvocation,实现取消操作和重做操作。
例子:有一个TapMe按钮,点击后数字加1,Undo按钮执行取消操作,Redo按钮执行重做操作,ClearActions执行清除栈的操作。
@interface ViewController ()
{
IBOutlet UILabel *mLabel; //显示的按钮
IBOutlet UIButton *redoButton; //重做的按钮
IBOutlet UIButton *undoButton; //取消的按钮
IBOutlet UIButton *clearButton; //清除的按钮
int number; //总共的点击次数
NSUndoManager *undoManager;
}
- (IBAction)redoTapped:(id)sender;
- (IBAction)tapMeTapped:(id)sender;
- (IBAction)undoTapped:(id)sender;
- (IBAction)clearTapped:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
undoManager = [[NSUndoManager alloc] init];
redoButton.hidden = YES;
undoButton.hidden = YES;
}
//点击按钮点击
- (IBAction)tapMeTapped:(id)sender
{
[self addNumber];
}
- (void)addNumber
{
number ++;
//一个取消操作的NSInvocation对象在Undo栈压栈---包括取消操作的对象和方法
[[undoManager prepareWithInvocationTarget:self] subNumber];
mLabel.text = [NSString stringWithFormat:@"有效点击数为%d",number];
[self refreshpage];
}
- (void)subNumber
{
number --;
//一个重新操作的NSInvocation对象在Redo栈压栈---包括重新操作的对象和方法
[[undoManager prepareWithInvocationTarget:self] addNumber];
mLabel.text = [NSString stringWithFormat:@"有效点击数为%d",number];
[self refreshpage];
}
//重做操作
- (IBAction)redoTapped:(id)sender
{
[undoManager redo]; //Redo栈的Invocation被调用,并被弹出栈
}
//取消操作
- (IBAction)undoTapped:(id)sender
{
[undoManager undo]; //Undo栈的Invocation被调用,并被弹出栈
}
//clearAction按钮被点击
- (IBAction)clearTapped:(id)sender
{
[undoManager removeAllActions]; //两个栈里面的所有NSInvocation对象都被弹出清空
[self refreshpage];
}
- (void)refreshpage
{
undoButton.hidden = !undoManager.canUndo;
redoButton.hidden = !undoManager.canRedo;
}