Chapter 09 – NSUndoManager (C#實現 + 全網原創)

此例子針對NSDocument實現了tableview 每一行添加/刪除的undo/redo,以及每一個單元格內容編輯的undo/redo。基於NSDocument類的實現。PersonModel + NSMutableArray和前面的例子是一樣的,就不重複貼了。採用Array Controller實現view-based tableview的綁定(不會的,翻前面的例子)。在貼程式碼前,要注意一下幾點。

1. NSUndoManager類下的prepareWithInvocationTarget成員函數,在xamarin中是有bug的。至今微軟還沒有修復,因為xamarin在轉換C#到objective-c程式碼時,默認調用了C#格式。其次,NSProxy的C#格式沒有IntPtr的構造函數。

2. 因為第一點原因,我們採用objc_msgSend來進行原始的objective-c格式調用。這個是一個Dll的導出函數,格式為: {返回值類型}objc_msgSend{參數1類型}{參數2類型}….{參數N類型}。我這裡詳細講解一個例子,其餘的都是一樣。

 

 

 這個聲明,對應的C#下的成員函數是這樣的格式.

 

 

 大家認真閱讀我的源程式碼後,就會明白原理了。好了。看下xcode的布局,記住別忘了設置每個單元格可編輯。如果都看到這裡了,說明基本的知識都會了。關於xcode的使用,自己從之前的例子一步一步學習。

完整的核心程式碼來啦!!!!在NSDocument的子類RMDocument下實現。xcode中的Array Controller的綁定之後我不再說了,默認是之前例子一樣的綁定。不會的,自己去看之前的例子。

 

 

 聲明需要採用objective-c格式調用的函數,避免bug 產生。

 

 

 有序KVO下的添加和刪除函數,記住Export導出的時候,名字有講究的。這是因為NSProxy代理時,需要格式化的名字。其次,採用objc_msgSend調用prepareWithInvocationTarget,這樣就避開了bug。

 

 

 至此,如果你編譯的話,只需要刪除StartObservingPerson和StopObservingPerson就會成功。但是呢,只能undo/redo添加和刪除的操作,不能undo/redo單元格編輯的內容。為了完善功能,我們需要對每一個PersonModel添加一個Observer,這樣的話,單元格內容編輯完成後,會自動調用ObserveValue成員函數(大家可以查看這個函數的協議導出全稱,就是objective-c下的”observeValueForKeyPath:ofObject:change:context:”)。現在看看如果添加Observer吧,定義一個KVOContext來區分不用的操作。

 

 

 

 

 

 至此,如果你將”Add Employee”按鈕綁定到Array Controller下的”Add” 或 “Insert”操作,就算基本完成啦。但是呢,我還要繼續,實現點擊「Add Employee」後,讓焦點集中在第一列的單元格上,並且等待用戶去編輯。如果想實現這個功能,那麼就不要綁定Array Controller下的”Add”或”Insert”操作。

 

 

好啦。測試下。可惜我不會弄動圖圖,所以大家不能看到redo/undo的所有操作。但是,已經全部實現。

 

 

 點擊”Add Employee”後,默認第一列處於可編輯狀態。

將其改成”New Person1″,然後再點2次”Add Employee”。把第二行的Raise改成「6」

 

 然後刪除第二行,undo兩次。

 

 最後redo兩次。哈哈哈哈。行和單元格數據的undo/redo都能工作了。

 

 最後退出。下一個例子會實現如何保存修改。