弊社iOSアプリをとりあえずCatalyst対応してみた

# TL;DR
- 現時点でCatalyst対応はかなり厳しい
- Firebaseはプッシュ通知が対応していないがRealtime Databaseが使える
- Cocoapodsを使っている場合はAssetsLibraryを手動で依存から外す必要がある

弊社で提供しているCASTというサービスはスマートフォン向けにアプリを提供しているためPC向けのアプリは提供していませんが、Catalystに対応のためにどういった作業が必要なのか興味がありやってみることにしました。

# 環境
- macOS Catalina 10.15
- Xcode 11.1
- iOS Development Version 11.0
- Cocoapods 1.8.3

# プロジェクトのCatalyst対応
Catalyst対応は驚くほど簡単です。

![スクリーンショット 2019-10-13 16.46.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/4de259d5-839f-f2de-9fae-b49d9c7aadce.png)

デバイス一覧にiPadに加えMacが追加されているので、両方にチェックをつけます。確認ダイアログのEnableを押せばMac向けビルド用Configが自動で追加され、自動で署名周りも面倒を見てくれます。この辺りはさすがのXcodeですね。

iPadにチェックをつけないとMacにもチェックがつけられないので、原則iPadにも対応する必要があります。
例えばActionSheetはsourceViewを指定しないとMacでアプリがフリーズしてしまいます。

**ここまでは順調でした・・・**

# ライブラリのCatalyst対応
ビルドできるようになるまでに対応したことを順番に解説します。

## Resource Bundleへの署名
まず初めにでたエラーはこれです。

![スクリーンショット 2019-10-13 16.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/3def30b5-eb35-4741-0d97-99369808583e.png)

> Signing for "XLPagerTabStrip-XLPagerTabStrip" requires a development team.

これはResource Bundleという画像などをライブラリの一部として配布する方式で、Catalyst向けにビルドするにはこれにアプリと同じチームに所属させる必要があるようです。
Cocoapods経由でこれらのライブラリを入れていたため、Podsのプロジェクトから該当するライブラリのSigning & Capabilitiesから、Teamを自分のTeamに設定します。

![スクリーンショット 2019-10-13 16.55.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/79c9b9ab-c79b-00c1-60b3-c67c165131da.png)

なおこれはPodsのプロジェクトの設定のため`pod install`するたびにこの変更はリセットされます・・・

## AssetsLibraryのリンクを削除
次はこちらのエラーです。

![スクリーンショット 2019-10-13 17.20.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/6cea6392-46b8-6593-c4d5-0f9d8d8ab56e.png)

> framework not found AssetsLibrary

AssetsLibraryは昔のiOSバージョンで使われていた画像を取得するためのライブラリのようですが、現在はiOSでDeprecatedとなっており、Catalystにはそもそもそのライブラリが収録されていないようです。
しかしかなり古いライブラリのためプロジェクト内を見ても使っている箇所はありませんでした。そこでプロジェクト内のテキストを検索かけてみると意外なところがひっかかりました。

![スクリーンショット 2019-10-13 20.16.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/825eb683-09e9-4282-2bc3-28365789c009.png)

そう、Podsプロジェクトファイルの中でした。どうもobjc向けビルドの互換性維持のためにcocoapodsが自動で追加しているようです。

`-framework "AssetsLibrary"` までがワンセットのようなので、これを全て取り除きます。

なおこれはPodsのプロジェクトの設定のため`pod install`するたびにこの変更はリセットされます**(2回目)**

## サポートしていないライブラリの削除
ここが一番大変でした。

Catalystに対応していないライブラリはビルドできませんので、丸ごと削除しなければならないのです。
これがどれが非対応なのかはビルドしないとわからず、また1個ずつしか教えてくれません。

なので根気よく
**ビルド->ビルドエラー->対応していないライブラリをPodfileから削除->pod install->上のビルドエラー解除->ビルド**
を成功するまで繰り返さなければなりません・・・

Podfileから消した現時点で未対応のライブラリ一覧です。

- pod 'AppsFlyerFramework'
- pod 'Crashlytics'
- pod 'KeychainAccess'
- pod 'Fabric'
- pod 'Firebase/Analytics'
- pod 'Firebase/Messaging'
- pod 'Firebase/RemoteConfig'
- pod 'RealmSwift'
- pod 'Repro'
- pod 'ZendeskSDK'

さすがにここまで対応していないとなるとプロダクションは無理ですね。

意外にもRealmはcocoapodsから消したあと、Swift Package Manager(SPM)経由でインストールすると使えました。
SPMはXcode11からGUIで使えるようになったので、SPM対応のライブラリは積極的にこちらに移すと良さそうです。
![スクリーンショット 2019-10-13 20.25.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/4ef8d52c-8847-74c8-6d10-998852591b23.png)

Firebase周りはプッシュ通知に対応できなかったものの、RealtimeDatabaseのライブラリはビルドできました。

## Other Linker Flagsの掃除
pod installしてもリンカの指定が残ってしまうことがあるので、その場合は手動で消します。

ターゲットのBuild Settingsから「Other linker flags」で検索すると出てくる長いオプションをダブルクリックで開き、Podから消したライブラリをここからも消していきます。

![スクリーンショット 2019-10-13 17.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/e032eef7-84ac-cb0a-f436-851922500216.png)

上のframeworkとしたのライブラリ名がセットのようなので2行ずつ消していきます。

これをビルドが成功するまで繰り返します・・・私の場合は消したpodの数だけなので10回これを繰り返しようやくビルド成功までこぎつけました！

# 実行!
![スクリーンショット 2019-10-13 20.31.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/e3b13115-b4fd-20db-020e-ef73578cc954.png)
いきなり崩壊してますね・・・上のロゴはLottieというライブラリを使っていてアニメーションするのですが、その配置があまりよくないようです。でもボタンは普通に押せますし、PushやModalもiOSのUIKitと同じように動きます。

## シフト表
![スクリーンショット 2019-10-13 18.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/a4a2c7fa-5aa0-cd6c-3a0e-b11542d9fb13.png)
かなりヌルっと動きます。

![スクリーンショット 2019-10-13 20.02.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/3b059e56-1e85-e0b5-04f8-ccf0ec30d0f4.png)
弊社エンジニア渾身の力作、多段Tabも問題なく動いています。SUGOI

## チャット
![スクリーンショット 2019-10-13 18.50.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/9b907b70-23c3-ca6a-4739-04e9c0c2d996.png)
プッシュ通知は対応していませんが、Firebase RDBが使えるのでリアルタイムでチャットができました。

## カメラ・写真
iOSと同じくパーミッションの確認が行われます。写真はMacの写真アプリに登録されている画像が選択できるようになっていました。
![スクリーンショット 2019-10-13 20.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/72d20c84-47be-a27a-ea6e-99f5660f5167.png)
ただiPhoneと違いMacはインカメしかないので本来の意図したカメラの使い方は難しそうですね・・・

## SFSafariView
SFSafariViewControllerはそのままSafariを直接開く挙動になります。

## UINavigationView
Safariのようにトラックパッド2本指で戻るような動作ができます。

## UIScrollView
シミュレータのくせでつい引っ張ってスクロールしがちですが、普通にトラックパッドの2本指でスクロールできます。縦横どちらともいけます。

## UIAlertController
Macのダイアログと同じ挙動になりました。
![スクリーンショット 2019-10-13 20.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/efc42554-0f19-8c5c-b78f-f7daf898d61e.png)


カスタムビューを突っ込んだ場合はウィンドウ内に表示されるようです。この辺りはよくできてますね。
![スクリーンショット 2019-10-13 20.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/33c3089d-b109-7224-d1ad-ce0b4f2f3538.png)

## UNUserNotification
Macの標準の通知として表示されました。

## その他
<img width="961" alt="スクリーンショット 2019-10-13 20.36.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/ac745ad8-e929-d519-434a-a210548e0360.png">

基本的にモーダルはウィンドウ内でオーバーレイ表示されるようです。なのでiOS13のようなハーフモーダルで閉じれることを期待するとMacでは閉じられなくなるようです。WWDCでも閉じるボタンは置きましょうと言っていましたしね。

# パッケージング
Macアプリと同じ手順でできるようです。My Macを選択しながらアーカイブするとMac向けのアーカイブができます。署名を行えば.app形式のファイルが手に入り、Xcodeを起動しなくてもアプリが実行できるようになります。

---

# 所感
ビルド成功までにもっていくのにかなりのハードルがあるものの、一度ビルドできてしまえばUIKitの再現度は非常に高いと感じました。

また先日TwitterがCatalyst対応をリリースされていましたが、非常によくできており改めて感心しました。