5.3K Views
October 31, 22
スライド概要
Mac Catalystで macOS用アプリを作る 2021.10.15 Mobile Act ONLINE #6 itok@そらかぜ
itok@そらかぜ • • いとうけい(itok) の中の人 • モバイルアプリエンジニア 兼 CEO • 副業でフリーランス的 • https://itok.jp/, https://sorakaze.co.jp/, @itokjp
所在地:京都市中京区 社員1人=自分
実績 自社 受託
iOS / Android / macOS / Windows / サーバ 一人でやってます(デザイン以外)
Mac Catalystとは
iPadアプリをmacOS上で動かす仕組み UIKitをmacOS上で動かす仕組み
AppKit UIKit macOS iOS iPadOS watchOS tvOS UIのフレームワークは別物
iPadアプリをmacOSで動かす • Apple Silicon製Mac限定 ➡ 一部のユーザのみ、iPadアプリとまったく同じ • SwiftUIで共通化 ➡ 新規作成(or • フルスクラッチ) Mac Catalyst ➡ 既存のリソースを有効活用?
たとえば
iOS / iPadOSアプリ
macOSで動かす 開発中
Mac Catalystの構造
Catalystの構造 注:イメージ AppKit UIKit 実装としてはUIKit側がメイン AppKitのガワをかぶって動いている macOS
クラス間の関係 UIKit AppKit UIApplication NSApplication UIScene NSWindow UIWindow UIViewController macOS
クラス間の関係 UIKit AppKit UIApplication NSApplication UIScene NSWindow UIWindow UIViewController おたがいのことは 関知していない macOS
実際にやってみる
はじめかた
小ネタ集
Multiple windows Windowを閉じるとアプリは終了する 終了させたくない場合は multiple windowsに対応する →UIScene / UISceneDelegate
Multiple windows 開発中
UIパーツ UISwitch.title Big Sur以降
UIパーツ button.menu = UIMenu(title: "", options: .displayInline, children: [ UIAction(title: "item1", handler: { _ in }), UIAction(title: "item2", handler: { _ in }), UIAction(title: "item3", handler: { _ in }), UIAction(title: "item4", handler: { _ in }) ]) button.showsMenuAsPrimaryAction = true
色 iPadOS macOS https://developer.apple.com/design/human-interface-guidelines/ mac-catalyst/overview/visual-design/
AppKitさわりたい
AppKitの恩恵
Bundle経由で AppKitにアクセス UIKit AppKit UIApplication NSApplication UIScene NSWindow UIWindow Bundle UIViewController macOS
Bundleの構成 Plugin protocol AppKit UIKit Bundle ViewController AppKitPlugin macOS
Bundle作成
Plugin.swift import Foundation @objc(Plugin) protocol Plugin: NSObjectProtocol { init() func doSomethingWithAppKit() } UIKit側に見せるprotocolを定義
AppPlugin.swift import AppKit class AppKitPlugin: NSObject, Plugin { required override init() { } func doSomethingWithAppKit() { let bar = NSStatusBar.system statusItem = bar.statusItem(withLength: 100) statusItem?.button?.title = "..." } } AppKitを使った実装
Info.plist <key>NSPrincipalClass</key> <string>AppKitPlugin</string> クラス名を隠ぺい (UIKit側から具象クラスを知る必要がなくなる)
ViewController.swift import UIKit class ViewController: UIViewController { func loadPlugin() { let bundleFileName = "AppKitPlugin.bundle" guard let bundleURL = Bundle.main.builtInPlugInsURL?.appendingPathComponent(bundleFileName), let bundle = Bundle(url: bundleURL) else { return } guard let pluginClass = bundle.principalClass as? Plugin.Type else { return } let plugin = pluginClass.init() plugin.doSomethingWithAppKit() } }
まとめ • Mac Catalyst • macOS用アプリを作る選択肢の一つとして • 既存リソースを活用しつつ macOSでも同じユーザ体験を • • Widgetを広く使ってもらうためには便利かも iPadアプリの移植を検討してみては?