2011-11-23 31 views
5

Tôi đang cố triển khai NSUndoManager trong ứng dụng iOS của mình. Tôi có chức năng hoàn tác để làm việc, nhưng không phải là phần làm lại. Tôi khá mới để phát triển iOS và đây là lần đầu tiên tôi đã sử dụng NSUndoManager vì vậy nó có thể là một cái gì đó tầm thường.Khó triển khai chức năng làm lại NSUndoManager

Ứng dụng của tôi là một ứng dụng vẽ/ghi chú, tôi có một ngăn xếp hoàn tác/làm lại với mười số UIImage s cuối cùng (Tôi không biết đây có phải là cách hiệu quả nhất) trong một mảng hay không. Khi người dùng thực hiện thay đổi đối với hình ảnh hiện tại, hình ảnh cũ được đẩy lên ngăn xếp và hình ảnh đầu tiên trong mảng bị xóa nếu mảng đã có mười đối tượng. Tôi có một biến thể hiện int mà tôi sử dụng để theo dõi các đối tượng trong mảng và đảm bảo rằng hình ảnh chính xác được hiển thị. Mã của tôi trông như thế này:

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

Khi tôi bấm vào lùi lại hoặc làm lại nút resetImage nên được gọi, và thiết lập hình ảnh hiện tại để đối tượng kế tiếp hoặc trước đó trong đống hình ảnh của tôi (giá trị hiện tại của undoRedoStackIndex) , điều này chỉ xảy ra khi tôi nhấp vào hoàn tác, nhưng không làm lại.

Giải pháp & & || cách tốt hơn để làm điều đó sẽ được đánh giá cao.

+0

@JoshCaswell Tôi đã thêm một số giải thích cho câu hỏi của mình. – Anders

Trả lời

6

Bạn không cần phải theo dõi các thay đổi, đây là những gì trình quản lý hoàn tác dành cho.

Thực hiện một phương pháp thể quay ngược lại như thế này:

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

Đây là nó. Để hoàn tác thay đổi, chỉ cần gọi [_undoManager undo] để thực hiện lại cuộc gọi [_undoManager redo]. Khi bạn yêu cầu trình quản lý hoàn tác hoàn tác, trình quản lý sẽ gọi phương thức này bằng hình ảnh cũ. Nếu bạn sử dụng các nút tùy chỉnh cho Hoàn tác thao tác, bạn có thể xác thực nó bằng cách sử dụng [NSUndoManager canUndo], v.v.

Không có giới hạn về số lần hoàn tác. Nếu bạn cần làm sạch ngăn xếp hoàn tác tại một số điểm, chỉ cần gọi phương thức removeAllActions.

+0

Cảm ơn bạn, làm cho nó hoạt động. Nghi ngờ rằng nó đã được dễ dàng hơn tôi đã thực hiện nó. Cảm ơn. // Anders – Anders

+0

@Davyd hi, bạn có thể giúp tôi điều này không :) "đăng thông báo cập nhật giao diện người dùng" cách cập nhật UIImage? –

+0

Một phương pháp với trình quản lý hoàn tác như tôi đã đăng được cho là được sử dụng trong mô hình dữ liệu. Đây là lý do tại sao tôi đã nhận xét về việc đặt thông báo. Ví dụ: [[NSNotificationCentre defaultCentre] postNotification: XXMyDataModelDidChangeImageNotification object: self]. Điều này có nghĩa là phải có một bộ điều khiển xem ở đâu đó với một khung nhìn (UIImageView) thực sự hiển thị hình ảnh. Bộ điều khiển chế độ xem này nên đăng ký thông báo từ mô hình dữ liệu và cập nhật chế độ xem khi nhận được thông báo. Hoặc một KVO có thể được sử dụng. Tôi hi vọng cái này giúp được. – Davyd

Các vấn đề liên quan