2012-10-02 4 views
1

블록 코드에 일부 실행 취소/다시 실행 (NSOpenPanel에서 일부 파일 가져 오기)을 추가하려고합니다. 코드가 블록에서 시작되는 한 주 코드는 작동하지만 NSUndoManager 코드는 저장되지 않습니다. 어떤 오류도주지 않는다. NSUndoManager 코드는로하지 블록블록 내에서 NSUndoManager 사용

NSUndoManager 코드는 다음을하여야 할 예에 한 곳에서도 작동합니다

// Undo Work 
id undoObject = [NSApp targetForAction:@selector(undoManager) to:nil from:self]; 
NSUndoManager *undoManager = [undoObject undoManager]; 
[[undoManager prepareWithInvocationTarget:self] deleteImages]; 
[undoManager setActionName:@"import images"]; 

코드가 수행하고 작동하지 않습니다을 보여줍니다 :

/* NSUndoManager code works */ 
NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 
[openPanel beginSheetModalForWindow:[self.windowController window] 
        completionHandler:^(NSInteger result) { 
         if (result == NSFileHandlingPanelOKButton) { 
          /* NSUndoManager code does not work, 
          it also does not work inside importImages: */ 
          [self importImages:[openPanel URLs]]; 
         } else { 
          [openPanel close]; 
         } 
        }]; 
/* NSUndoManager code works */ 
+0

여기에 냉소적이지 않습니까? "작품"이 조금 더 구체적으로 무엇을 의미하는지 설명해 주시겠습니까? 또한 didnt 작업 블록에서 undomanager 코드를 버렸습니다. 이전에 작성한 인스턴스를 사용하려는 경우 또는 블록 내부에서 [undoManager undoManager]를 호출하는 경우 알려주지 않음 (팩토리 메소드는 그대로 사용하도록되어 있으며 기본 인스턴스를 유지하는 데 별다른 의미가 없음) 변수가 작은 호출을 제외하고는 코드 명확성이 향상됩니다. –

답변

0

블록이 스택에 있으므로 실행 취소 작업이 호출 될 때 실행 취소 관리자 객체가 이미 할당 해제되어 있거나 그렇지 않은 경우 nil로 설정됩니다. 실행 취소 관리자가 활성 상태인지 확인하려면, 선언은 클래스 인스턴스 또는 __block syn 사용 (ARC없이) 세금 :

당신이 실행 취소 관리자와 완료
__block NSUndoManager* undoManager; 
NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 
[openPanel beginSheetModalForWindow:[self.windowController window] 
        completionHandler:^(NSInteger result) { 
         if (result == NSFileHandlingPanelOKButton) { 
          id undoObject = [NSApp targetForAction:@selector(undoManager) to:nil from:self]; 
          undoManager=[undoObject undoManager]; 
          [[undoManager prepareWithInvocationTarget:self] deleteImages]; 
          [undoManager setActionName:@"import images"]; 
          [self importImages:[openPanel URLs]]; 
         } else { 
          [openPanel close]; 
         } 
        }]; 

, 당신이 전무로 설정할 수 있습니다.

+0

실행 취소 관리자에 대한 포인터는 블록 내에서 액세스되는지 여부에 관계없이 변경되지 않습니다. 이 경우 __block은 아무런 영향을 미치지 않습니다. 그리고 블록 내부에서 실행 취소 관리자의 값을 재설정하면 위험 할 수 있습니다. 누군가의 스택에 포인터 값을 속이기 때문입니다. 다시 포인터가 변경되지 않고 __block은 스택에 할당 된 값을 수정하고 단순히 값을 읽고 메서드를 호출하는 것이 아니라 * 수정할 때 유용합니다. –