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

今天咱们要为这个画板增长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 git