4.2K Views
May 15, 22
スライド概要
To be written.
#macOS native Mac Catalyst Hacking ~macOSでHomeKitアプリを開発するために Yuichi Yoshida © 2022 Yuichi Yoshida. All rights reserved. Redistribution or public display not permitted without written permission from Yuichi Yoshida.
自己紹介 • sonson • 昔,2tchという2ちゃんビューアを作ってた. • iOSの本も書いてたけど,今は昔・・・・ • 本業は,画像認識とか,機械学習とか,そういうの
HomeConMenuをどぞ Mac App Storeで公開中 ソースコードも公開中 https://github.com/sonsongithub/HomeConMenu
ことの発端 • なんでmacからHomeKitデバイスの操作がこんなにやりにくいのか iOSはまだマシ.2stepでオン・オフできる アプリをわざわざ起動して・・ウィンドウもでかい
macOSアプリで作ったろ HomeKitがない・・・?だと・・・? Home.appは,Appleがズルしてるってことか!!!!!!!
HomeKit.frameworkはCatalyst専用 • HomeKitは,iOS/iPad OSのみだが,Mac Catalystなら使える • おっしゃ!!!Mac Catalystやったら使ったことある!!! • これで,メニューバー常駐でデバイス操作するの作ろうっと! しゅーりょー
bundleによるCatalystの改善 なんとしても,AppKitにCatalystからアクセスしたい 1. Dynamicというライブラリを使う 1. 2. Private APIにアクセスしやすくするやつ Bundleを使う 1. macOSのみでビルドされたバイナリをCatalystのバイナリにバンドルとして付属させる 2. 実行時にmacOSのみでBundleをロードし,使う https://betterprogramming.pub/how-to-access-the-appkit-api-from-mac-catalyst-apps-2184527020b5
どっち? Dynamic Bundle 怪しいプライベートAPIを辿ってアクセス レビューア(ヤクザ)にいちゃもんつけられる 後ろ指刺されることはない・・・はず 正規のルート!!のはず 🤔 😀 https://betterprogramming.pub/how-to-access-the-appkit-api-from-mac-catalyst-apps-2184527020b5
誤解を恐れないイメージ Catalystバイナリ UIKit/Mac Catalyst HomeKit AppKit/Cocoa(本当?)
誤解を恐れないイメージ Catalystバイナリ Bundle UIKit/Mac Catalyst HomeKit AppKit/Cocoa(本当?)
誤解を恐れないイメージ Catalystバイナリ Bundle UIKit/Mac Catalyst HomeKit AppKit/Cocoa(本当?) macOSのみをターゲットにして実装する
誤解を恐れないイメージ Catalystバイナリ 実行時にロード Bundle UIKit/Mac Catalyst HomeKit AppKit/Cocoa(本当?)
誤解を恐れないイメージ UIKitとMac Catalystしか話せない やりとりはお互いの環境に共通する型 Obj-Cで使える型 Anyなどで通信 Bundle Catalystバイナリ UIKit/Mac Catalyst HomeKit AppKit/Cocoa(本当?) AppKit/Cocoaしか話せない
イメージ UIKit HomeKit APIを叩くなど Mac Catalyst iOSController mac2ios Protocol 参照 Bundle MacOSController iOS2Mac Protocol こいつは実行時にロード AppKit/Cocoa NSMenuを作るなど
iOSの新規プロジェクト
Mac Catalystをオン
macOS BundleをTargetに追加
適当に名前をつける
Principle classをセットする
macOS BundleをCatalystでインポートする
BundleとCatalystの境界 やりとりするクラスは NSObjectProtocoloに準拠しないとダメ BundleとCatalystの境界を結ぶプロトコルなので,元のCatalyst, Bundleの両方のターゲットに追加する. ここには,StringやUUIDなどのAppKitでも,UIKitでも共通して含まれる型しか宣言できない.
いよいよBundle本体を作る 名前は,MacControllerとかにした Obj-Cの仕組みを使うので,bridging headerを追加しとく
ここではCocoaが使える ターゲットは,Bundleだけに追加. ここでは,自由にAppKit, Cocoaが使える.Catalyst側から呼び出したい処理を関数で実装しておく.
Catalyst側からロードする 複数クラスがあったり,Principal Classが間違っていたりすると ここで失敗する.ちゃんと確認すること.
Catalyst側から呼び出せる
うまくいかないとき • • コンパイル • プロトコルのUIKitとAppKitの変数がごっちゃになってる • 使えないクラス,型を使っている 実行時 • Bundleからクラスをロードするときに型を間違ってる • デバッガでちゃんと型通りのものがロードされているか確認
必要な工夫 • String, Int, Anyみたいなものしか渡せない • AnyにしてBundle側に持たせるとかはできる • Optionalは渡せないが,例外は飛ばせる • asyncのメソッドは,リンカがコケる.なぜ? • #if !os(macOS)で処理の切り分けは可能 • HomeKitは,すべてにUUIDが振られていたので,実装しやすかった • “Application is agent (UIElement)”などがInfo.plistで指定できたりした • SwiftUIをAppKit側に渡せないかと画策してみたがダメだった・・・・・
その他の問題 • 署名関連 • HomeKitを使うMac Cataslytのアプリは,notarizeできないし,署名もできないので,配布できない • • • 無署名は配布できるが,署名のないアプリはHomeKitにアクセスできない・・・・ HomeKitを使うMac Cataslytのアプリは,Mac App Storeでしか配布できない Mac App Storeのアイコン • Catalystでデフォルトのアイコンアセットを使うとMac App Storeのアプリアイコンがおかしくなる • Macアプリのアイコンアセットを作り直し,それをアプリアイコンにセットする必要がある • iOSベースの奴は何か問題がある・・・・?
まとめ • macOSでHomeKitアプリを作るために • Mac CatalystでもAppKit/Cocoaは触れる • DynamicライブラリとBundleの二つがある • Bundleアプローチが楽だけど,インタフェースが大変 • optionalが渡せないので,(あれ?nullableとかなかったっけ?)例外でやるとよい • macOSでHomeKitを使うアプリは,Mac App Storedでしか配布できない