2011-11-15 39 views
0

當使用複雜模型時,NSUndoManager無法撤消。NSUndoManager撤消不能在iOS上使用核心數據

這是我的模特。

core data model

我有一個Singleton,它利用核心數據的東西照顧,這是它的初始化:

 model =[NSManagedObjectModel mergedModelFromBundles:nil]; 

     NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; 

     NSString *path = pathInDocumentDirectory(@"store.data"); 
     NSURL *storeURL = [NSURL fileURLWithPath:path]; 

     NSError *error = nil; 

     if(![psc addPersistentStoreWithType:NSSQLiteStoreType 
           configuration:nil 
             URL:storeURL 
            options:nil 
             error:&error]) { 
      [NSException raise:@"Open failed" format:@"Reason: %@", [error localizedDescription]]; 
     } 

     context = [[NSManagedObjectContext alloc] init]; 

     NSUndoManager *contextUndoManager = [[NSUndoManager alloc] init]; 
     [contextUndoManager setLevelsOfUndo:20];  
     [context setUndoManager:contextUndoManager]; 

     [context setPersistentStoreCoordinator:psc]; 

因爲我有一個調用[自我initWithEntity的init方法每個實體... ]然後進入一些屬性。這是半邊實體的例子:

- (id) initWithVertex:(Vertex*) vert inManagedObjectContext: context { 

    NSEntityDescription* tEntityDescription = [NSEntityDescription entityForName: @"HalfEdge" 
                  inManagedObjectContext: context]; 

    self = [self initWithEntity: tEntityDescription insertIntoManagedObjectContext: context];  
    if(self) { 
     self.lastVertex = vert; 
     [self.lastVertex addHalfEdgeObject:self]; 
    } 

    return self; 
} 

當用戶添加了一個新的繪圖創建一個新的繪圖實體,然後讓用戶添加點錄音屏幕。對於每個點,rutine都會執行,可能會添加和/或刪除三角形實體,半邊和頂點。這是電話:

[[[DrawingsStore sharedStore].managedObjectContext undoManager] beginUndoGrouping]; 

[delaunay addPoint:CGPointMake(localizacion.x-dummy.bounds.size.width/2, localizacion.y-dummy.bounds.size.height/2)]; 

[[DrawingsStore sharedStore].managedObjectContext processPendingChanges]; 
[[[DrawingsStore sharedStore].managedObjectContext undoManager] endUndoGrouping]; 

正如你所看到的,我設置了一個撤消組裏面發生的所有事情。

然後當按下按鈕時,我正在調用[[上下文撤銷管理器]撤銷];但它什麼都不做。

我在撤消之前和之後打印一個提取,它是相同的。我可以看到rutine正在正常工作,將所有正確的實體添加到核心數據中,但是它根本不會撤消任何操作。

編輯與sugestions從Aderstedt

好吧,我刪除了NSManagedObject子類自定義init方法和創建一個類的方法是這樣的:

+ (HalfEdge*) addWithVertex:(Vertex*) vert inManagedObjectContext: context { 

    HalfEdge* halfEdge = [NSEntityDescription insertNewObjectForEntityForName:@"HalfEdge" inManagedObjectContext:context]; 

    if(halfEdge) { 
     halfEdge.lastVertex = vert; 
     [halfEdge.lastVertex addHalfEdgeObject:self]; 
    } 

    return halfEdge; 
} 

還是一樣的結果。對象被創建,撤消不起作用。 (canUndo返回1)

編輯

哇,我剛剛註冊的UndoManager的NSUndoManagerCheckpointNotification,一旦我點擊撤消它被張貼永遠像一個循環。好吧,現在我知道我一定在某個地方做錯了什麼,但是......在哪裏?

回答

2

好的,我發現了。原來我看着錯誤的地方。

試圖調試NSUndoManager我註冊了通知,發現NSUndoManagerCheckpointNotification一遍又一遍地被調用。

[delaunay addPoint ...]對模型進行了所有更改。但同時還有一個渲染例程運行,將三角形渲染到屏幕上。在那個例程中,我設置了這些三角形的顏色。我需要在那裏做,因爲在渲染屏幕背景之前,我不知道應該放的顏色。

對NSManagedObject子類Triangle的color屬性所做的更改導致NSUndoManagerCheckpointNotification被觸發並且撤消操作失效。如果我刪除它,撤消作品。

所以我想我只需要添加這一點,所以在所做的更改使不使它的撤消堆棧。

[[[DibujosStore sharedStore] managedObjectContext] processPendingChanges]; 
[[[[DibujosStore sharedStore] managedObjectContext] undoManager] disableUndoRegistration]; 
[renderer render]; 
[[[DibujosStore sharedStore] managedObjectContext] processPendingChanges];   
[[[[DibujosStore sharedStore] managedObjectContext] undoManager] enableUndoRegistration]; 
-1

您正在創建NSManagedObject實例The Wrong Way™。使用

- [NSEntityDescription insertNewObjectForEntityForName:... inManagedObjectContext...] 

插入新的對象。如果你想插入時爲對象做定製加工,在你NSManagedObject子類中覆蓋

- (void)awakeFromInsert 

。請檢查覈心數據文檔,明確指出您不希望覆蓋initWithEntity...。現在,至於你的撤銷問題,你的電話

[delaunay addPoint:CGPointMake(localizacion.x-dummy.bounds.size.width/2, localizacion.y-dummy.bounds.size.height/2)]; 

......它確實會改變核心數據對象的任何屬性?其他實例變量,緩存數組et.c.將不會被自動註冊爲撤消。如果你更改核心數據對象的屬性,請檢查看看[context undoManager]不是零。

+0

感謝您的回覆。我會嘗試你所說的。 但我沒有閱讀文檔關於繼承NSManagedObject,並且你可以看到,我沒有真正覆蓋initWithEntity ......我知道這似乎並沒有太正確做到這一點,但我看到它的地方,它實際上似乎工作,正如我所說的實體正在創建並添加到核心數據庫。 至於awakeFromInsert ...有沒有辦法將這些參數傳遞給初始值設定項? – Odrakir

+0

'-insertNewObjectForEntityForName'返回插入的對象,您可以使用它來設置一些初始參數。 – Aderstedt

+0

我編輯了你採取的方式(見上文)。仍然沒有撤消。 – Odrakir