NSUndoManager отменить не работает с Core Data на iOS - PullRequest
0 голосов
/ 15 ноября 2011

У меня проблема с NSUndoManager, который не удаляется при работе со сложной моделью.

Это моя модель.

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];

Для каждой сущности у меня есть метод init, который вызывает [self initWithEntity ...] и затем вводит некоторые свойства. Это пример сущности HalfEdge:

- (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;
}

Когда пользователь добавляет новый чертеж, я создаю новый объект Drawing и затем позволяю пользователю добавлять точки, прикоснувшись к экрану. Для каждой точки будет выполняться рутина, которая может добавлять и / или удалять треугольные объекты, половинки и вершины. Это вызов:

[[[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];

Как видите, я установил группу отмены для всего, что происходит внутри этой рутины.

Затем, когда нажимается кнопка, я звоню [[context undoManager] undo]; но это ничего не делает.

Я печатаю выборку до и после отмены, и это то же самое. Я вижу, что рутин работает правильно, добавляя все правильные сущности в основные данные, но затем он вообще ничего не отменяет.

РЕДАКТИРОВАТЬ с предложениями от Aderstedt

Хорошо, я удалил пользовательский метод init для подклассов NSManagedObject и создал метод класса следующим образом:

+ (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)

EDIT

Ничего себе, я только что зарегистрировался для NSUndoManagerCheckpointNotification от undoManager, и как только я нажму кнопку отмены, он будет опубликован навсегда, как в цикле. Хорошо, теперь я знаю, что где-то что-то не так делаю, но ... где?

Ответы [ 2 ]

2 голосов
/ 15 ноября 2011

Хорошо, я узнал.Оказывается, я искал не в том месте.

Попытка отладки NSUndoManager Я зарегистрировался для уведомлений и обнаружил, что NSUndoManagerCheckpointNotification вызывается снова и снова.

[delaunay addPoint ...]вносит все изменения в модель.Но в то же время существует процедура рендеринга, которая отображает треугольники на экране.В этой процедуре я установил цвет этих треугольников.Мне нужно сделать это там, потому что я не знаю цвет, который я должен поставить перед рендерингом фона экрана.

Эти изменения в атрибуте цвета треугольника подкласса NSManagedObject вызывали запуск NSUndoManagerCheckpointNotificationи отменить, чтобы не работать.Если я удаляю это, отмена работает.

Так что я решил, что мне просто нужно добавить это, чтобы изменения, сделанные во время рендеринга, не вносились в стек отмены.

[[[DibujosStore sharedStore] managedObjectContext] processPendingChanges];
[[[[DibujosStore sharedStore] managedObjectContext] undoManager] disableUndoRegistration];
[renderer render];
[[[DibujosStore sharedStore] managedObjectContext] processPendingChanges];         
[[[[DibujosStore sharedStore] managedObjectContext] undoManager] enableUndoRegistration];
0 голосов
/ 15 ноября 2011

Вы создаете NSManagedObject экземпляров The Wrong Way ™. Используйте

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

для вставки новых объектов. Если вы хотите выполнить пользовательскую обработку для объекта, когда он вставлен, переопределите

- (void)awakeFromInsert

в вашем NSManagedObject подклассе. Пожалуйста, проверьте документацию Core Data, в которой прямо указано, что вам не рекомендуется переопределять initWithEntity.... Теперь, что касается вашей проблемы отмены, ваш звонок на

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

... действительно ли это меняет какие-либо атрибуты на объектах Core Data? Другие переменные экземпляра, кэшированные массивы и т. Д. не будет автоматически зарегистрирован для отмены. Если вы действительно измените атрибуты объектов Core Data, убедитесь, что [context undoManager] не ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...