見出し画像

[cocoa][swift]NSUndoManager

NSUndoManagerの利用は、Swiftで楽になったと思うが、その仕組みが見えにくくなったと思うので、Objective-Cの場合から説明する。

CocoaのUndoとRedoは、NSInvocationというクラスでNSObjectの子クラスとメソッドを保持し、それをNSUndoManager内のスタックで管理することで実現している。

なんらかの操作を行うと、Undoに必要なNSInvocationのインスタンスがUndoスタックに積まれていく。

ユーザがUndoを行うと、Redoに必要なNSInvocationのインスタンスがRedoスタックに積まれていく。

Objective-Cのコードで、以下のようになる。

- (void)makeItHotter
{
   temperature = temperature + 10;
   [[undoManager prepareWithInvocationTarget:self] makeItColder];
}
- (void)makeItColder
{
   temperature = temperature - 10;
   [[undoManager prepareWithInvocationTarget:self] makeItHotter];
}

makeItHotterで温度を10度上げて、makeItColderをNSUndoManagerに積む。

makeItColderでは、温度を10度下げて、makeItHotterをNSUndoManagerに積む。

これをSwiftを書く場合、積むメソッドのselectorを用意するのが面倒になるのだが、selectorを必要としないメソッドが用意されていた。以下のようになる。

func makeItHotter() {
   var temperature = self.textField.intValue
   temperature = temperature + 10
   self.undoManager?.registerUndo(withTarget: self, handler: {
       vc in
       vc.makeItColder()
   })
   self.textField.intValue = temperature
}
func makeItColder() {
   var temperature = self.textField.intValue
   temperature = temperature - 10
   self.undoManager?.registerUndo(withTarget: self, handler: {
       vc in
       vc.makeItHotter()
   })
   self.textField.intValue = temperature
}

ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/mac/Temperature - GitHub

【関連情報】
Cocoa Programming for Mac OS X
Cocoa.swift
Cocoa勉強会 関東
Cocoa練習帳

いいなと思ったら応援しよう!