這個隨筆的內容以上一個隨筆爲基礎,(在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