zoukankan      html  css  js  c++  java
  • iOS: 为画板App增加 Undo/Redo(撤销/重做)操作

    这个随笔的内容以上一个随笔为基础,(在iOS中实现一个简单的画板),上一个随笔实现了一个简单的画板:

     
    今天我们要为这个画板增加Undo/Redo操作,当画错了一笔,可以撤销它,或者撤销之后后悔了,还可以还原。而且我们要通过晃动手机来触发Undo/Redo的选择。
     
    这个demo使用NSUndoManager实现Undo/Redo操作,NSUndoManager 的实现原理是它作为一个记录器,每次数据变化,我们要用这个记录器记录一个相反的操作,当需要undo的时候,它通过执行这个相反的操作就可以实现了。对于这个画板demo,我们通过把array中的Line首尾连接起来实现的,所以要想还原到上次的状态,我们通过从array中remove最后添加的那条线就可以实现了。
     
    NSUndoManager需要两个步骤:
    第一步,注册NSUndoManger操作,既上边提到的注册一个相反的操作。(先只实现undo操作)
    首先添加一个相反的操作,即一个从array中remove Line的方法,方法名就叫removeLine:
     
    然后修改addLine方法,注册刚刚添加的removeLine方法:
     
    但是这里有一个问题:因为当手指在屏幕移动的时候,touchMove方法会被持续多次触发,所以画一笔,是由多个Line组成的。所以addLine会调用多次,如果我们直接undo,只是remove掉了一条Line,但是画一笔是由多个Line组成,这样只能移掉一笔中的一部分,即结尾的那部分。
     
    那要怎么办呢?如何一次移除多个Line,即画一笔所包含的一组Line。
    NSUndoManager有一个分组的概念,就是为了解决这类问题的。
    正常情况下,画一笔肯定会触发3个方法,依次是touchBegan, touchMove 和 touchEnd,所以我们可以通过touchBegan和touchEnd就能分辨出画一笔的开始和结束。既:
     
    这样我们再执行撤销的时候就是一次remove一组的Line了。
     
    第二步,执行Undo
    在UI添加一个按钮,作为Undo按钮,按钮的点击事件中简单地调用undo方法就可以了。既:
     
    Undo操作这样就算是完成了。
    Redo操作和Undo操作道理一样,我们只需要修改下removeLine方法,当remove一条Line的时候,也注册一个相反的操作,即注册addLine方法,修改后的removeLine方法:
     
    晃动触发Undo/Redo操作
    其实我们根本不需要在UI添加Undo/Redo按钮,直接晃动手机就会自动弹出Undo/Redo选项,而且晃动的功能是自动打开的。
    如果需要关闭它,需要设置:
    在这个demo中,请不要将此属性设置为NO。
     
    最后看下效果:(在模拟器中无法晃动,使用快捷键进行了模拟)
     

    相关源代码:github 

  • 相关阅读:
    UVA 11525 好大好大的排列(线段树)
    UVA 11525 好大好大的排列(线段树)
    UVALive 4108城市天际线,混杂着递归与非递归的线段树
    UVALive 4108城市天际线,混杂着递归与非递归的线段树
    zencart搜索结果页面静态化 advanced_search_result
    .htaccess 一段神奇的跳转代码
    清除zencart分类页多页后面的&disp_order &sort字符串的方法
    zencart只有购买过此产品的客户才能评价产品
    mysql自增字段AUTO_INCREMENT重排或归零
    mysql语句修改zencart产品原价为特价的倍数
  • 原文地址:https://www.cnblogs.com/sirkevin/p/4069179.html
Copyright © 2011-2022 走看看