2020年1月5日TweetPocket久しぶりに新しいアプリを開発することになった。Macの両対応を目指すことにした。Macで必要に応じて効率的にUIの分岐を行えるようにした。先に言いたいことをまとめると下記のようになる。macOSの両方で動作する。下記の部分のみはiOSとmacOSでコードを分けたが、それ以外の部分はOSによる処理の分岐なしで、完全に一つのコードで両アプリが動いている。iOSでは「フォトライブラリから動画を読み込む」ボタンを表示するが、macOSでは表示しないiOSでは出力された動画をUIActivityViewControllerを表示してDropboxなどの他のアプリに渡せるようにするが、macOSでは「ファイルに保存」ダイアログを表示する字幕の「スタイル」編集画面で、iPadでは要素をつめて表示したり一部ポップアップ表示したりするいずれも、分岐しなくてもアプリとして使うこと自体はできるが、各デバイスの使われ方を考慮した際に挙動を変えた方が使い勝手が良くなりそうだったので、分岐させた。9月ぐらいから開発を始めて、本当はもっと早くリリースできるかなと思っていたのだが、色々と苦戦して12月末にようやく最初のバージョンをリリースできた。以降、どのようなところで苦戦していたのかを記していく。SwiftUI大前提として、SwiftUIによるUI開発・管理はStoryboard時代に比べてとても先進的で便利になったと思う。一度慣れてしまうと、SwiftUIを使わないUI開発に戻るのはなかなか辛い。最低限使えるようになるまでは結構苦労した。Web上の情報が古い問題SwiftUIを勉強する上で、最初に厄介だったのがこの問題だった。SwiftUIは6月のWWDCで発表されたのだが、9月に正式版がリリースされるまでの間に結構色々な仕様の変更が行われている。公式ドキュメントを読むだけで完全に使い方やパターンを理解できれば良いのだが、なかなかそうもいかない場面も多く、困ったときは検索をしてみるのだが、ウェブ上には6月のベータ版時点での仕様に基づいた情報が非常に多く、これには結構惑わされた。どれが古い仕様で、どれが最新の仕様なのか、ある程度理解が進めば判別ができるのだが、最初に勉強するタイミングではその判断に苦労した。最新の公式ドキュメントを徹底的に読むことと、ウェブ上の情報は「古い仕様かも?」という目で読んでいった方が良い。コードとエラーの内容が直接リンクしない問題SwiftUI上でListを使うと内部的にはUITableViewが生成される。そこでエラーが発生するとエラーログにはUITableViewのエラーとして表示される。ListとUITableViewの関係性を理解していないと原因の特定ができない。ボタンが押されたら特定のテキストフィールドに自動でフォーカスが移動するようにする、みたいな処理はSwiftUIだけでは実現することができない。標準のTextFieldでは、日本語の入力が正しく受け付けられなかったり、複数行の入力に対応させることができない。このような場合には、UIViewRepresentableを使って自前でViewを実装する必要があるのだが、この部分の実装は複雑になりがちで多少苦労した。コンパイラが原因と関係ないところでエラーを返す問題SwiftUIでは、コードに問題があるとビルド時にXcodeがエラーを表示してくれるのだが、なぜか本来のエラー原因と全然関係がないところで、全然関係がないエラーが表示されることがある。ウェブ上では、同じような症状に遭遇した人の情報がちらほらあるので、おそらくビルドキャッシュの問題か、コンパイラの問題だと思うのだが、残念ながら原因と対処法はよくわかっていない。いう時は「別の箇所が原因かも?」という疑いの目でデバッグをしていくことになるのだが、なかなかこの作業は難易度が高く効率が悪かった。Catalystファイルを開くダイアログを出せない問題CatalystとSwiftUIを同時に使うとUIDocumentPickerViewControllerやUIActivityViewControllerが画面に表示されないこれに関しては、詳細をこちらに分けて記述した。Catalystを使ってmacOSアプリを作る場合は、macOS固有の機能を直接呼び出すことができない。ファイルを開くダイアログを表示するにも、NSOpenPanelではなくUIDocumentPickerViewControllerを使用する必要があるのだが、iPadでは問題なく動作するものが、macOSではなぜかうまく動かないなどの問題が発生し、対応に苦労した。リリース方法がわからない問題リリースに関しても、情報が少なく苦戦した。Storeへのデリバリーを行えば良い。このやり方はWWDCのビデオでは説明されていたのだが、公式ドキュメント上ではこの手順を見つけることができなかった。自分の場合は、運悪く下記の現象にもハマってしまっていた。https://stackoverflow.com/questions/46148523/profile-doesnt-match-the-entitlements-files-value-for-the-application-identifi投稿の説明通り、CapabilitiesでiCloudを一旦ONにした上でOFFにしてビルドしなおしたところ、最終的に無事アプリをAppStoreに提出することができた。同様の現象にハマってしまった人は試してみて欲しい。リリース後の開発について上述の通り、開発からAppStoreでの配信までは、結構苦戦をしたので思ったよりはリリースまで時間がかかってしまった。Catalystの良さをすぐに実感することになった。今回リリースしたアプリは、コードとしてはそこそこ複雑でUIの要素も多いのだが、冒頭に書いた通りiOS版とmacOS版で処理を分けている箇所は全体のうちでUI関連の3箇所しか存在しない。おかげで、アップデートの効率が非常に良い。SwiftUIで、Storyboardと違ってOSによる内容の分岐を最小限の工数でかけることによる、UI開発の効率アップも非常に大きい。基本的にはmacOSで動作確認したものはほぼそのままiOSで動作するため、macOSアプリとして開発を進めて、iPad実機やシミュレータは動作確認に使う程度で大丈夫、というのもありがたい。おかげで、出先でiPadを持っていない状態でも開発を進めていくことができる。リリースまでの道のりは長かったが、リリース後は期待以上の世界が広がっていた。macOSのハイブリッドアプリを開発するにはとても有用な機能だし、組み合わせることで効果が最大化するのは間違いないが、それぞれ習得まではそこそこ学習が必要だ。この二つは組み合わせると更に学習の難易度が上がってしまうので、個別にある程度習得をしてから組み合わせに挑戦した方が良い。小さいアプリ開発で慣れるいきなり大きなアプリをこの組み合わせで作るのはとても難易度が高い。macOSアプリの感覚で設計をはじめてしまうとあとで大改修が必要になってしまう可能性が高い。小さなアプリを開発し、リリースするところまでを経験してから大きなアプリの開発に着手した方が良い。自分の場合も、一つものすごく小さなアプリの開発・リリースを行ったが、その経験がとても役に立った。macOSアプリの開発を行っていない自分にとってはなかなか難易度の高い挑戦になった。世にまとまっているノウハウが少ないことや、組み合わせによって発生する問題などもあり、そこそこの経験と忍耐力が求められる。macOSそれぞれのアプリをアップデートしていくことができる。macOS両対応アプリを開発・運用できることのメリットは非常に大きい。覚悟を決めたら、小さいアプリの開発から使って行ったら良いのでは無いかと思う。PM日本語でちゃんと読めるCatalystの記事、初めて見たと思います。ありがとうございました。macOS/iOS」がリリース。コメントをキャンセルメールアドレスが公開されることはありません。*ウェブサイトご意見、ご感想をお願いします。