이게 무려 5년이나 된 글이고, 그 사이에 저장/열기 패널은 액션시트로 변경되면서 많은 부분이 바뀌었기에 다시 한 번 정리합니다. (2016-11-23)
macOS앱에서 일반적인 파일 포맷을 다루는 경우1, 파일을 저장하거나 열려고 할 때 파일의 위치를 지정해주기 위해서 저장 / 열기 패널을 열게 된다. 이 패널은 모달하게 동작하면서 저장위치를 선택할 수 있게 하는 macOS의 공통 UI를 사용한다. NSOpenPanel, NSSavePanel은 이 때 사용하는 클래스이며, 다음과 같이 동작한다.
- 패널을 모달하게 열어 사용자로 하여금 저장/로딩할 파일을 설정하게 한다.
- 델리게이트를 통해 사용자의 선택이 완료되었을 때, 처리할 동작을 위임할 수 있다.
파일 열기
NSOpenPanel
은 파일을 열 때 사용하는 패널로 다음과 같은 식으로 동작하게 할 수 있다.
- 델리게이트를 정의한다.
- 패널 인스턴스를 생성한다.
- 패널을 설정한다. (초기 위치 및 UI 상의 여러 메시지 들)
- 패널을 보여준다.
사용자가 ok 혹은 cancel 버튼을 클릭하면 패널은 델리게이트에 대해서 각 액션별로 정해진 동작을 수행하게 하고 UI를 닫는다.2
델리게이트
사실 begin(completionHandler:)
를 호출하게 되면 단순히 패널을 띄우는 것이 아니라 이 때부터 패널 객체는 델리게이트와 끊임없이 서로 대화하면서 상황을 공유하게 된다. 이 때의 자세한 상황을 들여다보면 다음과 같은 케이스에서 호출되는 델리게이트 메소드들이 정의되어 있다.
- 특정 파일/디렉토리의 URL이 패널 내에서 활성화될 것인지 여부를 확인한다. (Open시)
- 사용자가 선택한 주소가 유효한지를 확인한다.
- 사용자가 디렉토리를 변경하면, 이를 델리게이트에게 알려준다.
- 사용자가 패널을 확장하려하면[^3] 이를 델리게이트에게 알려준다.
- 사용자가 선택했던 파일을 변경하면 이를 델리게이트에게 알려준다.
- 파일을 선택하고 버튼을 클릭해 확인하면 이를 델리게이트에게 알려준다
사실 이 경우에 델리게이트는 파일 선택과 관련된 여러 액션의 디테일을 조정하는 역할을 수행하며, 동시에 파일 선택을 완료했을 때의 정보도 획득해갈 수 있지만, 보통은 다음과 같이 델리게이트 없이도 충분히 사용이 가능하다. runModal()
의 경우에 패널은 모달하게 동작한다. 패널이 모달하게 표시되는 동안에 원래 윈도는 사용자와 상호작용할 수 없으므로 runModal()
은 블럭킹 함수로 실행된다. 이 함수의 리턴 값은 어떤 버튼이 눌려졌는지를 구분해주는 정수값이다.
func openDocument() {
let panel = NSOpenPanel()
panel.title = "Open"
panel.nameFieldLabel = "File to open"
panel.message = "select files to opne"
if NSFileHandlingPannelOKButton == panel.runModal() {
for url in panel.urls {
// URL별 처리
}
}
}
실제 패널 실행은 크게 세 가지 모드가 사용될 수 있다.
- 앱 전체에 대해 모달하게 표시한다:
runModal()
사용 - 특정 창에 대해서만 모달하게 표시한다. :
beginSheetModal(for:,completionHandler:)
- 모드리스 창으로 실행한다. :
begin(completionHandler:)
암튼 대략의 내용은 이러하고 보다 자세한 내용은 레퍼런스 페이지를 참고하도록 한다.
레퍼런스
NSOpenSavePanelDelegate
: https://developer.apple.com/reference/appkit/nsopensavepaneldelegateNSOpenPanel
: https://developer.apple.com/reference/appkit/nsopenpanelNSSavePanel
: https://developer.apple.com/reference/appkit/nssavepanel
핑백: [Cocoa] NSSound를 통한 초간단 사운드 재생 | Wireframe
댓글이 닫혔습니다.