ObjecTips

Swift & Objective-C で iOS とか macOS とか

macOS 10.15 AppKit の変更点

AppKit で気になった追加API

NSScreen
var localizedName: String { get }

localizedName - NSScreen | Apple Developer Documentation

これまではスクリーン(macOS ではディスプレイ)に関する情報の取得は CGDisplay 系のAPIで取得していた気がする。
もうちょっと上のレイヤーで簡単にリストアップする事ができる様になりそう。
ちなみに MacBook Pro + Sidecar の環境で実行してみたところ

Build-in Retina Display
AirPlay Display

と表示された。

NSColorSampler

NSColorSampler - AppKit | Apple Developer Documentation

使い方は簡単

NSColorSampler().show { color in
}

これでスポイトツールが表示される。
既存では NSColorPanel を表示してそこからユーザがスポイトツールを選択し使用する事はできたが、NSColorSampler を使うと直接スポイトツールを起動する事ができる。面白い。

NSResponder, NSEvent 周りの changeMode
func changeMode(with event: NSEvent)

changeMode(with:) - NSResponder | Apple Developer Documentation

static var changeMode: NSEvent.EventTypeMask { get }

changeMode - NSEvent.EventTypeMask | Apple Developer Documentation

case changeMode = 38

NSEvent.EventType.changeMode - NSEvent.EventType | Apple Developer Documentation

オンラインドキュメントを見ても Xcode でSwiftファイルを見ても何も載っていないなーと思って探していたら NSResponder の Objective-C header ファイルにコメントが載っていた。

f:id:Koze:20190613122703p:plain

/* Issued in response to a double-tap on the side of the Apple Pencil */ - (void)changeModeWithEvent:(NSEvent *)event API_AVAILABLE(macos(10.15));

macOS で Apple Pencil?
Sidecar 利用時にMacアプリで Apple Pencil のサイドダブルタップが取得できるのだろうかと思い以下の様に、firstRespoder のインスタンスで変更を受け取る実装と NSEvent のモニターメソッドで変更受け取る実装を試してみたけど、Apple Pencil のダブルタップのアクションは受け取れなかった。

    override func changeMode(with event: NSEvent) {
        // not called
        print(event)
    }
    NSEvent.addGlobalMonitorForEvents(matching: .changeMode) { event in
        // not called
        print(event)
    }
    NSEvent.addLocalMonitorForEvents(matching: .changeMode) { event -> NSEvent? in
        // not called
        print(event)
        return event
    }

MonitorForEvents(matching: .any) にするとApple Pencilのタッチ、ドラッグ、圧力などのイベント情報は取れた。ペンサイドのダブルタップのみ反応無し。
まだ beta でちゃんと動いていないのか、何か他の方法での実装が必要なのかも知れない。

追記

Apple Pencil のダブルタップのイベントが取得できなかった件、macOS 10.15 beta 2 で修正された模様。
以下の2箇所で取得できた。

    override func changeMode(with event: NSEvent) {
        // called when double tap
        print(event)
    }
    NSEvent.addGlobalMonitorForEvents(matching: .changeMode) { event in
        // called when double tap
        print(event)
    }

print(event) でイベントをログ出力すると以下の様に type=Translate と記載されているが

NSEvent: type=Translate loc=(174.379,278.68) time=1479.2 flags=0 win=0x100703440 winNum=532 ctxt=0x0

print(event.type.rawValue)rawValue を確認してみたところ値は 38 になっていたので changeMode のイベントで間違いなさそう。