UndoManagerの使い方

やり直し・繰り返しを制御するUndoManagerを使ったときに悩んだことをちょこっとメモ。 CoreDataやUIWebViewにはくっついてたりするので、自分でゴリゴリソースを書くことはあんましない・・・かも?

基本的な使い方

基本的には何かの処理をしたときに、その処理を打ち消す動作をUndoManagerに登録してあげます。 UndoするときにはUndoManagerが勝手にその打ち消す動作を実行してくれます。 処理の登録法は、例えばobjAのfunctionが打ち消す動作だとすると、

1
[[undoManager prepareWithInvocationTarget:objA] function];

と言った形になります。 引数がある時も同じです

1
[[undoManager prepareWithInvocationTarget:objA] functionWithObject:objB];

Redoは自動的に登録される

Redoに関しては何もソースを書く必要はありません。 UndoがきちんとできていればRedoは自動的に登録されます。 なぜかというと、undoする間にさらにそれを打ち消す動作がundoManagerに登録されるからです。 値Aを1→2に変えたとします。それを打ち消す動作は2→1に変える動作です。 この打ち消す動作である2→1の間にも更にそれを打ち消す動作である2→1がundoManagerに登録されます。 これがRedoの登録になります。 なので、undoがきちんとできていればRedoは勝手に登録されるんです。 ちょっとお得ですね!

自動でグループ化される

Widthを変更してHeightも変更するみたいなときは、undoしたときに一緒に元に戻って欲しいですよね? それを行なってくれるのがグループ化です。 WidthとHeightの値の変更を同じグループ内で行えば、undoしたときに一緒に元に戻ってくれます。 しかし、これもあまり意識しないでいいです。 何故ならば、自動でグループ化されるからです。 Widthを変更してHeightも変更するときはたいてい続けて処理を書きますよね?それは同じグループになります。 グループがわかれるのはシステムに処理が戻った時です。(変えたければ設定で変えられます。) 逆に言えばシステムに処理が戻らなければずっと同じグループなので、気を付けないと大変です。
グループ化、redoは何もしなくてもいいとはいえ、知識としては知っておかないと変なソースを書いてしまうので 頭の片隅にでも入れておくのがいいと思います。