Chapter 09 – NSUndoManager (C#實現 + 全網原創)
- 2022 年 8 月 20 日
- 筆記
- MacOS Cocoa - C#開發, Mac下的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都能工作了。
最後退出。下一個例子會實現如何保存修改。