zoukankan      html  css  js  c++  java
  • [ios2]NSUndoManager 【转】

    在Cocoa中使用NSUndoManager可以很方便的完成撤销操作。NSUndoManager会记录下修改、撤销操作的消息。这个机制使用两个NSInvocation对象栈。

         NSInvocation会把消息(选择器和接受者及参数)包装成一个对象,这个对象就是NSInvocation的实例。当一个对象收到它不理解的消 息时,消息发送机制会在报出错误前检查该对象是否实现了forwardInvocation这个方法。如果实现了,就会将消息打包成 NSInvocation对象,然后调用forwardInvocation方法。


        1) NSUndoManager工作原理
        当进行操作时,控制器会添加一个该操作的逆操作的invocation到Undo栈中。当进行Undo操作时,Undo操作的逆操作会倍添加到Redo栈中,就这样利用Undo和Redo两个堆栈巧妙的实现撤销操作。

        这里需要注意的是,堆栈中存放的都是NSInvocation实例。


        2)示例
        假设在我们的程序中有walkLeft以及这个方法的逆方法walkRight,我们可以这样来实现撤销功能。
    - (void) walkLeft
    {
        position = position + 10;
        [[undoManager prepareWithInvocationTarget:self] walkRight];
        [self showTheChangesToThePostion];
    }

        prepareWithInvocationTarget:方法记录了target并返回UndoManager,然后UndoManager重载了 forwardInvocation方法,也就将walkRight方法的Invocation添加到undo栈中了。
       
    - (void) walkRight
    {
        position = position - 10;
        [[undoManager prepareWithInvocationTarget:self] walkLeft];
        [self showTheChangesToThePostion];

    }


        UndoManager还可以设置撤销菜单动作的名称:
        [undoManager setActionName:@"Insert"];
    //===一下是我在源代码网站里复制过来的代码,有学习价值====//
    - (NSInvocation *) drawScribbleInvocation
    {
      NSMethodSignature *executeMethodSignature = [scribble_
                                                   methodSignatureForSelector:
                                                   @selector(addMark:
                                                             shouldAddToPreviousMark:)];
      NSInvocation *drawInvocation = [NSInvocation
                                      invocationWithMethodSignature:
                                      executeMethodSignature];
      [drawInvocation setTarget:scribble_];
      [drawInvocation setSelector:@selector(addMark:shouldAddToPreviousMark:)];
      BOOL attachToPreviousMark = NO;
      [drawInvocation setArgument:&attachToPreviousMark atIndex:3];
     
      return drawInvocation;
    }

    - (NSInvocation *) undrawScribbleInvocation
    {
      NSMethodSignature *unexecuteMethodSignature = [scribble_
                                                     methodSignatureForSelector:
                                                     @selector(removeMark:)];
      NSInvocation *undrawInvocation = [NSInvocation
                                        invocationWithMethodSignature:
                                        unexecuteMethodSignature];
      [undrawInvocation setTarget:scribble_];
      [undrawInvocation setSelector:@selector(removeMark:)];
     
      return undrawInvocation;
    }

    调用:
    [self executeInvocation:drawInvocation withUndoInvocation:undrawInvocation];
     
    - (void) executeInvocation:(NSInvocation *)invocation
            withUndoInvocation:(NSInvocation *)undoInvocation
    {
      [invocation retainArguments];

      [[self.undoManager prepareWithInvocationTarget:self]
       unexecuteInvocation:undoInvocation
       withRedoInvocation:invocation];
     
      [invocation invoke];
    }

    - (void) unexecuteInvocation:(NSInvocation *)invocation
              withRedoInvocation:(NSInvocation *)redoInvocation
    {  
      [[self.undoManager prepareWithInvocationTarget:self]
       executeInvocation:redoInvocation
       withUndoInvocation:invocation];
     
      [invocation invoke];
    }

     
     
  • 相关阅读:
    Go内建容器篇
    Go基础语法篇
    【区块链】比特币Merkle树
    【区块链】Fabric 术语
    Apache旗下项目
    【区块链】Fabric0.6 与1.0
    rc.local不起作用
    命令行模式启动VMWare虚拟机
    vsftpd 530 Login incorrect 根本原因和解决方案
    Oracle的undotbs01.dbf文件太大(占用大量磁盘空间)处理方法 ORA-01654 空间不足 ORA-01653
  • 原文地址:https://www.cnblogs.com/jinjiantong/p/3120386.html
Copyright © 2011-2022 走看看