2011-11-23 20 views
5

Próbuję zaimplementować NSUndoManager w mojej aplikacji na iOS. Mam funkcjonalność cofania do działania, ale nie część redo. Jestem całkiem nowy w rozwoju iOS i po raz pierwszy użyłem NSUndoManager, więc prawdopodobnie jest to trochę trywialne.Trudności z implementacją funkcji ponownego wywoływania NSUndoManager

Moja aplikacja jest aplikacją do robienia zdjęć/notatek, mam stos cofania/ponawiania z ostatnimi dziesięcioma UIImage s (nie wiem, czy jest to najbardziej efektywny sposób) w tablicy. Gdy użytkownik wprowadza zmiany w bieżącym obrazie, stary obraz jest przesyłany na stos, a pierwszy obraz w tablicy jest usuwany, jeśli macierz ma już dziesięć obiektów. Mam zmienną instancji int, której używam do śledzenia obiektów w tablicy i upewnienia się, że wyświetlany jest właściwy obraz. Mój kod wygląda następująco:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    if (oldImagesArrays.count >= 10) { 
     [oldImagesArrays removeObjectAtIndex:0]; 
    } 
    UIImage * currentImage = pageView.canvas.image; 
    if (currentImage != nil) { 
     [oldImagesArrays addObject:currentImage]; 
     undoRedoStackIndex = oldImagesArrays.count -1; 
    } 
    [...] 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    UIImage * currentImage = [oldImagesArrays lastObject]; 
    if (currentImage != pageView.canvas.image) { 
     [undoManager registerUndoWithTarget:self selector:@selector(resetImage) 
     object:currentImage]; 
    } 
} 

// Gets called when the undo button is clicked 
- (void)undoDrawing 
{ 
    [undoManager undo]; 
    [undoManager registerUndoWithTarget:self 
          selector:@selector(resetImage) 
          object:pageView.canvas.image]; 
    undoRedoStackIndex--; 
} 

// Gets called when the redo button is clicked 
- (void)redoDrawing 
{ 
    [undoManager redo]; 
    undoRedoStackIndex++; 
} 

- (void)resetImage 
{ 
    NSLog(@"Hello"); // This NSLog message only appears when I click undo. 
    pageView.canvas.image = [oldImagesArrays objectAtIndex:undoRedoStackIndex]; 
} 

Kiedy klikam cofnąć lub ponowić przycisków resetImage powinno się nazywa, i ustawić aktualny obraz do następnego lub poprzedniego obiektu w moim obrazu stosu (bieżącą wartość undoRedoStackIndex) , dzieje się tak tylko wtedy, gdy klikam Cofnij, ale nie ponawiam.

Rozwiązania & & || Lepsze sposoby robienia tego będą mile widziane.

+0

@JoshCaswell Dodałem trochę wyjaśnień do mojego pytania. – Anders

Odpowiedz

6

Nie musisz śledzić zmian, do czego służy menedżer cofania.

Złóż sposób cofnąć tak:

- (void)setImage:(UIImage*)image 
{ 
    if (_image != image) 
    { 
     [[_undoManager prepareWithInvocationTarget:self] setImage:_image]; // Here we let know the undo managed what image was used before 
     [_image release]; 
     _image = [image retain]; 

     // post notifications to update UI 
    } 
} 

To jest to. Aby cofnąć zmianę, wystarczy zadzwonić pod numer [_undoManager undo], aby ponownie zadzwonić pod numer [_undoManager redo]. Gdy powiesz kierownikowi cofania, aby cofnął, wywoła tę metodę ze starym obrazem. Jeśli użyjesz przycisków niestandardowych do operacji Cofnij, możesz je zweryfikować, używając [NSUndoManager canUndo], itp.

Nie ma ograniczeń co do liczby operacji cofania. Jeśli chcesz wyczyścić stos cofania w pewnym momencie, po prostu wywołaj metodę removeAllActions.

+0

Dziękuję, mam to do pracy. Podejrzewałem, że to było łatwiejsze niż to zrobiłem. Dzięki. // Anders – Anders

+0

@Davyd hi, czy możesz mi w tym pomóc :) "Powiadomienia pocztowe do aktualizacji UI" jak zaktualizować UIImage? –

+0

Metoda z menedżerem cofania, tak jak napisałem, ma być używana w modelu danych. Właśnie dlatego zamieściłem komentarz dotyczący zgłoszenia powiadomienia. Na przykład: [[NSNotificationCentre defaultCentre] postNotification: XXMyDataModelDidChangeImageNotification object: self]. Oznacza to, że powinien być gdzieś kontroler widoku z widokiem (UIImageView), który faktycznie wyświetla obraz. Ten kontroler widoku powinien subskrybować powiadomienie z modelu danych i aktualizować widok po otrzymaniu powiadomień. Alternatywnie można użyć KVO. Mam nadzieję, że to pomoże. – Davyd