본문 바로가기

Programing/My OSS

[Contact] 한글날 버전 v1.09

2020-10-12  버전: 2.0이 릴리즈 되었습니다.


한글날을 맞아 한글 자음과 모음을 합쳐주는 애플리케이션 버전을 업데이트했습니다.

시간이 없어 마이너 업데이트만 진행하였습니다.

릴리즈

Contact-v1.09.zip
3.30MB

SHA-1: 8c0321a0920bffb280144ba74e12aaa9faead3b9

Release: github.com/namhokim/cocoa_app/releases/tag/Contact-v1.09

추가 기능:  이번에 추가된 feature는 dock에 파일(들)을 drag & drop을 하면 변환되도록 하는 기능을 추가하였습니다.

천마디 말보다 하나의 동영상이 더 이해하기 쉽습니다. 3가지 케이스.

동일한 Dock의 아이콘 중 왼쪽이 구버전, 오른쪽이 신버전입니다.

CFBundleDocumentTypes

이 기능을 위해서는 Info.plist 에 CFBundleDocumentTypes 를 추가해주어야 합니다.

관련문서: 프로퍼티 리스트 키 > CFBundleDocumentTypes (Apple)

xcode에서는 이 이름이 Document types으로 보이므로 주의 할 필요가 있습니다.

파일 내부에는 CFBundleDocumentTypes 지만 Xcode에는 Document types 로 보인다.

 key 이름(텍스트 에디터) Xcode 설명 값의 타입
CFBundleDocumentTypes Document types key 이름 dict의 array
CFBundleTypeName Document type Name 타입의 이름 (필수) string
CFBundleTypeRole Role {Editor, Viewer, None, or Shell} string
CFBundleTypeExtensions CFBundleTypeExtensions 확장자들 string의 array
LSHandlerRank Handler rank 타입의 Owner / Open 만 지원? string
LSItemContentTypes Document Content Type UTIs Uniform Type Identifie들 타입 string의 array

UTI: developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html

이벤트 처리기

하지만 단순히 위에처럼 프로퍼티 추가만 해주면 동작하지 않습니다.

왜냐하면 처리해주는 핸들러가 없기 때문입니다. 지정된 핸들러가 없으면 아래와 같이 에러창이 뜹니다.

이 문서는 열 수 없습니다.

파일이 dock에 드롭이 되면 AppDelegate 에 openFiles 이벤드가 수행되는데 이 이벤트를 오버라이딩 해서 구현을 해주면 됩니다.

관련 문서: application(_:openFiles:) (Apple)

하지만 cocoa 초보 개발자는 위의 문서를 보고 어떻게 만들어야할지 잘 이해하지 못했습니다.

stackoverflow에는 objective-c로 예제가 되어 있어서 구현에 대한 감이 잘 오지 않았기 때문입니다.

-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
    NSLog(@"%@", filename);
    return YES;
}

문서를 찬찬히 살펴보니 AppDelegate의 NSApplicationDelegate에는 뼈대 함수들이 정의가 되어 있고 이것을 오버라이딩 하면 될 것 같았습니다.

AppDelegate body에서 openfiles라고 쳐보니 아래와 같이 후보가 들이 나옵니다.

선택을 하니 아래와 같이 뼈대를 만들어주었습니다.

사실 형태가 여러개의 파일을 받는 형태와 하나의 파일을 받는 시그너쳐가 있었습니다.

하지만  하나를 드롭하던 여러개를 드롭하던 항상 [Strings]들을 인자가 넘어오는 아래코드에서 위의 함수가 호출이 되네요.

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    // ... 제일 아래
    func application(_ sender: NSApplication, openFiles filenames: [String]) {
        print("mutiple: \(filenames[0])")
        print("size: \(filenames.count)")
    }
    
    func application(_ sender: NSApplication, openFile filename: String) -> Bool {
        print("single: \(filename)")
        return true
    }

AppDelegate 에서 ViewController 로 메시지 보내기

문제는 파일 이름처리하는 메인 로직이 ViewController에 있었습니다.

어떻게 하면 ViewController에 구현한 함수를 AppDelegate에서 호출할 수 있을까요?

NSApplication 에는 shared 라는 프로퍼티를 통해 하위 Controller로 접근할 수 있는 방법을 제공하고 있습니다.

구현에 대한 힌트는 stackoverflow에서 찾았습니다.

구현코드: github.com/namhokim/cocoa_app/blob/f52c5ce4ed9c492afa0a56dc0d0a48f755e731ef/Contact/Contact/AppDelegate.swift#L30