15

我正在研究一些使用NSOperation導入數據的代碼。我希望用戶能夠撤消在導入操作期間創建的NSManagedObject實例。取消在主線程中執行的核心數據插入

從我所知道的情況來看,對主線程執行的任何操作都不可能使用NSManagedObjectContext-undoManager。從使用核心數據編程指南節主題禁閉支持併發,我們有這兩個條件:

  1. 只的objectID應通過託管對象上下文之間 (上 單獨的線程)
  2. 被管對象 必須保存在 之前的上下文中才能使用objectID。

這是有道理的,因爲管理對象需要從專用存儲(NSManagedObjectContext)公共存儲(NSPersistentStore),他們可以共享之前移動。

不幸的是,-save:消息還會導致撤消堆棧中的任何託管對象被刪除。從同樣的引導件的存儲器管理使用核心數據部分:

託管具有掛起 變化(插入,缺失,或 更新)可以通過上下文 被保留,直到它們的上下文中的對象被髮送保存:, 重置,回滾或dealloc消息, 或相應數量的撤銷到 撤消更改。

我已經試過幾件事情要解決這一限制,一切最終導致恢復大部分工作都發生在主線程的(和紡紗沙灘球),以獲得任何線索撤消通過創建關閉對象工作主線程將非常感激。

-

的增強雷達已經提交:rdar://problem/8977725

+0

爲什麼不只是保留此操作插入的所有託管對象ID的日誌?這樣,如果用戶想要回滾,可以簡單地遍歷並刪除對象。如果您還必須回滾突變,那麼記錄關鍵/值更改也不難。看起來比試圖將其放到撤銷管理器中更簡單。 – ImHuntingWabbits 2011-02-26 08:53:39

+0

關於上述評論,你會如何提出重做? – wbyoung 2011-06-20 16:06:46

回答

0

不是專家,但我想你會什麼需要做的是創建第二個方面來進行操作,然後合併這兩個環境在一起。您應該能夠將合併作爲撤消步驟進行管理。請注意,這隻適用於將整個操作集作爲一個撤消步驟,就用戶而言。

+0

我已經在執行-mergeChangesFromContextDidSaveNotification:將導入上下文中的更改傳播到主線程中的上下文。問題是合併使用已存在於持久性存儲中的數據來調整對象圖。主線程上的NSManagedObjectContext沒有任何需要寫入持久性存儲的-insertedObjects或-updatedObjects。 – chockenberry 2011-02-09 17:39:00

0

假設您爲後臺線程使用單獨的上下文,並且一旦完成後,將[[backgroundContext undoManager] undo]推送到前臺線程的撤消堆棧上?我從來沒有嘗試過這樣的事情,但從我的頭頂來看,我想不出它不應該起作用的理由。

+0

你是什麼意思「[[backgroundContext undoManager]撤銷到前臺線程的撤消堆棧」?從我可以告訴撤消堆棧的內容是私人的... – chockenberry 2011-02-09 03:39:41

+0

[[[foregroundContext undoManager] prepareWithInvocationTarget:[backgroundContext undoManager]] undo]; (實際上,您也需要保存backgroundContext ...) – 2011-02-09 05:01:31

0

一個選項可能是讓您的導入線程持久化。即使線程完成導入,它也會進入空閒循環狀態。這樣您的線程ManagedObjectContext被保存在正確的線程中。然後,當用戶希望撤消更改時,向該線程發送消息以使用undomanager。

2

這個答案可能會有點反覆。如果我正確理解問題,那麼您正在執行導入,但導入完成後,您希望用戶能夠選擇從導入中保存的內容?

如果這是不正確的,請修正我的假設,我會更新這個答案。

如果它是正確的,那麼你可以做的是:

  1. 你的背景對象創建更改爲

    NSEntityDescription *myEntity = ... //Entity from your context 
    [[NSManagedObject alloc] initWithEntity:myEntity 
         insertIntoManagedObjectContext:nil]; 
    
  2. 存儲這些實體在數組中。
  3. 根據需要將實體傳遞迴主線程。
  4. 發佈您不想保留的任何物品
  5. 致電[myMainContext insertObject:managedObject]任何您想保留的物品。
  6. NSManagedObjectContext上執行保存。

由於這些實體是不是一個NSManagedObjectContext的一部分,但它們只存在於內存中,並應該是線程安全的,因爲他們還沒有束縛於一個NSManagedObjectContext

這當然是理論上的,需要測試。但它應該實現你的目標。

0

這是令人難以置信可能你已經考慮了這一點,並使用現有的undoManager你可能只是尋找一個解決方案,但以防萬一:

既然你插入的對象,而不是更新現有的,你做有權在導入每個批次時使用事務ID標記它們,在撤消的情況下在後臺線程中刪除它們。一個簡單的遞增NSNumber就足夠標籤。

不雅,但可行。