先日macOS Catalinaがリリースされました。それに伴いTwitter公式アプリもCatalystでmacOS化されてリリースされました。
Twitter
個人的に開発している# TypeもCatalystには向いているアプリなので是非やってみたいな常々思っていました。
そこに立ちはだかるのが利用しているライブラリ群です。
特に# Typeで大きく依存いているのがFirebaseです。
Firebaseのissueを覗いてみるといくつか Feature Request でCatalystのサポートが要求されている事が分かります。
Issues · firebase/firebase-ios-sdk · GitHub
これをウォッチしていると、Analyticsなどプライベートな機能を有するものを除き、コミュニティによる支援によってある程度の対応が済んだ事が発表されました。
macOS and tvOS | GitHub - firebase/firebase-ios-sdk: Firebase iOS SDK
今回# TypeでCatalyst対応を試みたので流れを公開します。
環境
- macOS Catalina(10.15)
- Xcode 11.0
前提条件
iPadOSに対応している必要があります。
(更に SceneDelegate
に対応しておいた方が良いかと思いますがこの辺りは試してないので余計な事は言わないでおきます)
Targetの分割
最初にiOSのターゲットのままは厳しそうだと感じたので、ターゲットを分割しました。(同じターゲットのままでももしかしたら通るかもしれないですが、iOS側で必要なframeworkのせいで進まない可能性もあるので、必要ないframeworkを削除しやすくする為には分割するのが楽だと思います)
今回は$(PRODUCT_NAME)Catalyst
の様な名前にしました。
Deployment InfoのDeviceを iPhone
を外して iPad
を残し、新たに Mac
を選択します。そうするとダイアログで確認されるので Enable
をクリック。
スキームの追加
ターゲットと同様に ${PRODUCT_NAME}Catalyst
を追加。
Podfileの修正
分割したターゲットに合わせてPodfile
を修正します。
target 'Type' do
use_frameworks!
pod 'Firebase/Core'
pod 'Firebase/Storage'
pod 'Firebase/AdMob'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Auth'
pod 'Firebase/Firestore'
pod 'Firebase/Messaging'
pod 'Firebase/Functions'
pod 'FirebaseFirestoreSwift'
pod 'Fabric'
pod 'Crashlytics'
pod 'SwiftLint'
pod 'SwiftFormat/CLI'
+
+ pod 'GoogleUtilities/AppDelegateSwizzler'
+ pod 'GoogleUtilities/MethodSwizzler'
+ pod 'GoogleUtilities/Network'
+ pod 'GoogleUtilities/NSData+zlib'
+ pod 'GoogleUtilities/AppDelegateSwizzler'
+ pod 'GoogleUtilities/Environment'
+ pod 'GoogleUtilities/Logger'
+ pod 'GoogleUtilities/UserDefaults'
+ pod 'GoogleUtilities/Reachability'
end
+
+target 'TypeCatalyst' do
+ use_frameworks!
+ pod 'FirebaseCore'
+ pod 'Firebase/Storage'
+ pod 'Firebase/RemoteConfig'
+ pod 'Firebase/Auth'
+ pod 'Firebase/Firestore'
+ pod 'Firebase/Messaging'
+ pod 'Firebase/Functions'
+ pod 'FirebaseFirestoreSwift'
+ pod 'GoogleUtilities/AppDelegateSwizzler'
+ pod 'GoogleUtilities/MethodSwizzler'
+ pod 'GoogleUtilities/Network'
+ pod 'GoogleUtilities/NSData+zlib'
+ pod 'GoogleUtilities/AppDelegateSwizzler'
+ pod 'GoogleUtilities/Environment'
+ pod 'GoogleUtilities/Logger'
+ pod 'GoogleUtilities/UserDefaults'
+ pod 'GoogleUtilities/Reachability'
+end
差分としてはAdMob, Fabric, Crashlytics, SwiftLint, SwiftFormatなどのmacOSでは不要なライブラリを外した様な感じです。
そして pod deintegrate && pod install
を実行。(多分 pod install
だけでも大丈夫だけど念の為)
2020/04/12追記
GoogleUtilities
系をそれぞれiOSとmacCatalyst用に追加が必要でした。
2020/04/12追記終わり
ビルドしてみる
先述したスキームを選択した状態で⌘+Bでビルドしてみます。
早速エラーが出ました。
gRPC+c++
が証明書関連でビルド出来ないと言われるのでPods
-> gRPC-C++
から Signing & Capabilities
で自分のチームを選択。
更にビルドしてみる。
先述したCatalystターゲットでは削除したライブラリが無いので途中でビルドがコケました。
ここから先はTry&Errorで対応していきます。
大抵は
#if !targetEnvironment(macCatalyst)
import Fabric
import Crashlytics
#endif
の様な感じで場合わけをしていくことになると思います。
色々直して更にビルドをしてみます。
Firebase Analytics辺りでコケた様に見えます。
Xcodeのプロジェクト全体から FIRAnalyticsConnector
を検索してみます。
この中から Pods-${PRODUCT_NAME}Catalyst.debug.xcconfig
と Pods-${PRODUCT_NAME}Catalyst.release.xcconfig
を修正します。
FIRAnalyticsConnector
、 GoogleAppMeasurement
、 FirebaseAnalytics
、 FirebaseAnalyticsInterop
辺りはmacOSに不要なので検索して諸々削除します。
- "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
- "${PODS_ROOT}/FirebaseAnalytics/Frameworks"
- "${PODS_ROOT}/Headers/Public/FirebaseAnalyticsInterop"
- -iframework "${PODS_ROOT}/FirebaseAnalytics/Frameworks"
- -iframework "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
- -framework "FIRAnalyticsConnector"
- -framework "GoogleAppMeasurement"
- -framework "FirebaseAnalytics"
抜粋するとこんな感じ。
2019/10/20追記
この記事を見た人からCatalystではpod 'Firebase/Core'
ではなく pod 'FirebaseCore'
を利用すると良いと情報をいただきました。
その様にすると、開発版ではこの部分の対応が不要になりました。
但し、Archiveをすると GoogleUtilities
が2度呼ばれるエラーが発生します。
下記の記事のWorkaroundを対応すると回避出来ます。
2019/10/20追記終わり
対応が済んで更にビルドしてみる。
Run script
でコケたのでCrashlytics、SwiftLint、SwiftFormatなどを削除。
さすがに疲れてきたので半ば諦めながら再ビルド...
🎉
無事ビルドが出来たので色々触ってみた所、色々修正は必要そうなので諸々対応していきました。
オチ
そろそろ一旦Test Flightにでも上げたいなという所まで対応して、ローカル環境でArchiveを試みた所...
gRPCのライブラリでヘッダーファイルが見つからないとエラーが出てしまいました。
こちらはFirebaseでもGitHub Issuesにあがっていました。
- gRPC-Core file not found (Mac Catalyst) · Issue #4007 · firebase/firebase-ios-sdk
- gRPC-Core fails to archive for Catalyst · Issue #20500 · grpc/grpc
補足(CocoaPods以外のライブラリについて)
元々Carthageも利用していましたが、Xcode 11 betaの段階でSwift Package化していたので、今回ほとんど対応不要でした。
(一部kishikawakatsumi/KeychainAccessがCatalystに対応していなかったので今回は削除して進めました)
2020/04/12追記
kishikawakatsumi/KeychainAccessもCatalyst対応されていたのでバージョンを上げるだけで利用できました。
2020/04/12追記終わり
まとめ
残念ながらArchiveに失敗し、Test Flightにアップロードが出来なかったのですが、開発環境ではビルドが成功したので時間を見て必要な対応があれば進めていこうと思います。
github.com/grpc/grpcをウォッチして、Archiveが出来る様になるまでは# TypeのmacOS化対応は様子見ですね。。
とほほ。。
もし、# TypeのmacOS化をお待ちの方がいましたらもう暫くお待ちください🙇🏻♂️
という事でCatalystに成功しなかったので記事のタイトルは [WIP]
のままです。
追記: 2020/04/12
gRPCのIssueのコメントにあるスクリプトを実行しながらArchiveを実行すれば最後までArchiveが可能になりました。
少し手直しをしたものがこちらです。
#!/usr/bin/env bash
# Semiautomatic workaround for the issue described in
# https://github.com/grpc/grpc/issues/20500
PRODUCT_NAME="Type"
trap "exit" INT
while true; do
sleep 0.1
_boring_ssl=$(find ~/Library/Developer/Xcode/DerivedData/${PRODUCT_NAME}* \
-name "BoringSSL-GRPC" | head -n1)
cd "$_boring_ssl/openssl_grpc.framework" && ln -s Versions/Current/Headers Headers &&
echo "Patched openssl_grpc"
_grpc_core=$(find ~/Library/Developer/Xcode/DerivedData/${PRODUCT_NAME}* \
-name "gRPC-Core" | head -n1)
cd "$_grpc_core/grpc.framework" && ln -s Versions/Current/Headers Headers &&
echo "Patched grpc"
done
PRODUCT_NAME
をご自身のアプリ名に合わせれば利用可能かと思います。
これを持って長い間付いていた WIP
を外します。