2010-07-21 47 views
1

我有一個基於Core Data的UIKit應用程序,它允許用戶在屏幕上拖動對象。在拖動對象時,我會更新每個touchesMoved:事件的位置屬性。爲了一次性支持撤消拖動操作,我在拖動的開始處開始一個新的撤消組,並在用戶擡起手指時結束組。核心數據撤消跨越多個運行循環週期的操作合併

爲了節省內存和快速撤消操作,我想合併屬於拖動操作的撤消數據,但是Core Data使這一點變得困難。問題是在每個運行循環週期結束時調用processPendingChanges,並強制核心數據爲該迭代中發生的位置更改生成新的撤消記錄。拖動操作可以輕鬆地累積數百個這樣的撤消記錄,除第一個之外,所有這些都是不必要的。

有沒有辦法讓我繼續使用Core Data的神奇內置撤銷支持,但不會在這樣的重複撤消記錄上浪費寶貴的內存?我喜歡我不需要關心在撤銷/重做操作中維護對象圖一致性,但是無法正確處理這些連續的屬性更新似乎是一個不爭的事實。

回答

3

我認爲設置撤消管理器setGroupsByEvent:會做你想做的。

設置一個布爾值,指定 是否接收機自動 組運行 循環中撤消操作。如果爲「是」,則接收方在每次通過 運行循環時創建 撤消組;如果不是,它不會。

更簡潔的解決方案可能是直到拖動事件結束時纔將對象位置提交給數據模型。

+0

不幸的是,'setGroupsByEvent:'在這裏沒有幫助。拖動跨越多個事件,所以除非我誤解了一些基本的東西,否則沒有辦法用'beginUndoGrouping' /'endUndoGrouping'明確分組我的更改 - 而'setGroupsByEvent'在已經有一個開放組的情況下變爲空操作。 在拖動手勢結束前不更改模型可能是最佳方式。問題是我沒有地方存儲瞬態位置 - 我直接從模型中進行渲染,沒有單獨的視圖對象。但也許這只是意味着現在是時候添加它們了! – 2010-07-23 21:38:36

+0

IIRC,將'groupsByEvent'設置爲'NO',您將得到一個超出運行循環的長撤銷組。 – TechZen 2010-07-24 02:45:50

+0

*嘆息*不,將'groupsByEvent'設置爲'NO'只會禁用隱式分組,因此您需要始終啓動和結束自己的組。是的,你自己創建的組顯然可以超越單循環迭代。這不是問題。 問題是在每次運行循環迭代結束時自動調用'performPendingChanges'引發的內存使用情況和性能問題。您建議的更清晰的解決方案恰好是一個很好的解決方法:如果模型僅在手勢結束時發生更改,則「performPendingChanges」不會在每次運行循環迭代中註冊新的撤銷操作。 – 2010-07-25 17:19:06

0

一種解決方案是在第一次拖動事件後禁用所有撤銷註冊,並保持禁用狀態直到整個手勢完成。

如果您有groupsByEvent,請記住撤銷管理器會在註冊關閉時忽略所有分組消息,包括在事件結束時自動結束隱式組的消息。所以,如果你打算請假登記在運行循環結束關掉,你就必須自己手動關閉隱性組:

[moc processPendingChanges]; 
while ([moc.undoManager groupingLevel]) 
    [moc.undoManager endUndoGrouping]; 
[moc.undoManager disableUndoRegistration]; 

一旦拖動動作完成後,您可以重新啓用撤銷登記用下面的代碼:

[moc processPendingChanges]; 
[moc.undoManager enableUndoRegistration]; 

這個解決方案的工作原理,但它有點kludgy。 TechZen建議的更清潔:在拖動手勢完成之前不要更新模型屬性。

+0

事實證明,更清潔的方法並不適合我的應用程序 - 系統地將一個單獨(可獨立調整的)視圖樹與我的模型對象並行引入會導致太多併發症。我結束了使用這個更簡單的解決方案。 – 2010-07-26 15:37:06