SwiftUIでmacOSとiOSをサポートするアプリを作ってみた
初めに
この記事はSwiftUI Advent Calendar 2022の24日目の記事です。
SwiftUIをベースにしたアプリでmacOSとiOSのマルチプラットフォームで動作するアプリを作ったので紹介します!
Use Xcode to develop a multiplatform app
WWDC22で発表されたXcode14の新機能に「単一ターゲットで複数のプラットフォームをサポートしたアプリを作れる」という機能があります。
従来はiOSアプリとmacOSアプリをサポートしたい場合は別のターゲットを用意する必要があったのですが、Xcode14からは単一のターゲットで開発できるようになりました。
これによってBuildSettingsやアプリの共通化したコードベース・アセットの共通化が簡単になると思います。
作ってみた
丁度夏くらいにCsv2Imgというcsvファイルをpng/pdfに変換できるアプリを作っていたので、そのアプリをmacOSとiOSに対応してみました。
GitHubに上げているのでもし良かったらスターをください
辛かったこと
macOSとiOSをサポートするに当たってインターフェースが異なる部分が多く、結局#if os
は所々使うことになりました。
NSxxxとUIxxx: Application / View / Responder / ViewRepresentable
毎回書くと大変なのでType.swift
というOSごとに違うインターフェースだけど同じような責務の型を定義しておくファイルを作りましたが、結局ViewModel内部でもos毎に処理を分ける必要があったのであまり恩恵は得られませんでした。
もっと綺麗にアーキテクチャ分けすれば共通化できるコードが増えると思います。
ファイルの選択方法
- iOS: UIDOcumentPickerViewController
- フォルダアプリからファイルを読み込む・ファイルを出力する
- macOS: NSOpenPanel
- Finder経由でファイルの読み書きをする
今回ユーザーがcsvのファイルを選択をする際にiOSとmacOSで別々のアプリから読み書きしたのでAPIを共通化できず分岐が必要でした。
カラー・描画
Appleが提供する色はOSごとに異なります。
NSColorにもUIColorにもseparator色はあるのですが、separatorColor
/ separator
と微妙に異なる命名がされており、以下のようにマクロで分けることになりました。
また、GraphicsContextを生成する処理もmacOSにはUIGraphicsBeginImageContext
やUIGraphicsImageRenderer
は存在しなく、一度NSImage
を作成してlockFocus
メソッドを呼んでからCGContextを取得する流れになっており、分岐が必要でした。
あとは同じCoreGraphicsでもiOSだと.zero
が左上になってmacOSだと左下になるので以下の分岐が必要でした。
他にもmacOSにはNavigationのpopアニメーションがなかったりと異なる点があり都度対応する必要があると思います。個人的意見ですが企業のようなデザイナーさんがいて仕様通りのデザインやサービス全体で統一されたデザインシステムがあるとSwifUIの中でもっとmacOSとiOS間で分岐処理が必要になってくると思いました。
良かったところ
SwiftUIで作れると状態管理が楽ちんなので個人的にはSwiftUI好きです。
終わりに
SwiftUIでの開発体験が来年再来年と良くなっていくと嬉しいです。来年もよろしくお願いします!
Discussion