🙌

CapacitorプラグインをSPM対応にマイグレーションする5ステップ

2024/11/27に公開

Capacitor iOSプラグインをCocoaPods対応だけではなく、SPMにも対応できるようマイグレーションしていきましょう。 SPMになぜ対応するのか、対応して何が嬉しいのかは以下をご覧ください。

https://zenn.dev/rdlabo/articles/4456315c9ca829

1. プラグインファイル名を変更する

ここでいう「プラグインファイル」は、 ios/Plugin 以下にあるヘッダーファイルとmファイル、あとSwiftファイルの中でも @obj がついており、プラグインとして先頭に呼び出されるファイルを指しています。古いプラグイン構成だと、以下の構成となっています。

  • Plugin.swift
  • Plugin.m
  • Plugin.h

これだとややこしいので、最近の構成である以下の構成にファイル名を変更します。 ** はプラグイン名で、例えばAdMobプラグインだと **Plugin.swiftAdMobPlugin.swift と読み替えてください。

  • **Plugin.swift
  • **Plugin.m
  • **Plugin.h

ちなみに、最終的に Plugin.xcodeproj 等のファイルは全部削除するので、リンク先まで修正することを考えてXcode上でリネームする必要はありません。単純にファイル名を変更するだけで大丈夫です。続いて、 **Pugin.swift を開いてみてください。 **Plugin という名称になっていなかったら変更が必要です。

- @objc(Stripe)
- public class Plugin: CAPPlugin {
+ @objc(StripePlugin)
+ public class StripePlugin: CAPPlugin {

2. capacitor-plugin-converterで変換する

https://github.com/ionic-team/capacitor-plugin-converter を使って、自動変換できる部分は自動変換します。この操作自体はとても簡単なのですが、まず任意の場所で以下のコマンドでzipファイルをDLします。

% curl -OL https://github.com/ionic-team/capacitor-plugin-converter/releases/latest/download/cap2spm.zip

で、ダブルクリックするとUnix実行ファイルになりますので、これを実行します。例えば、この実行ファイルをダウンロードした場所から、マイグレーションしたいペイメントプラグインが相対的に ./payment フォルダにあるとしましょう。上記の **.swift** 部分は PaymentPlugin です。その場合、以下を実行します。

% ./cap2spm payment --no-backup

--no-backup をつけないと、既存ファイルを .old ファイルとしてリネームして置いといてくれますが、ほとんどの場合はGitでプラグイン管理しているので不要でしょう。これを実行すると、 **Plugin.h**Plugin.m が削除され、その内容が **Plugin.swiftpluginMethods プロパティに移行されます。こんな感じで追加されると思ってください。

https://github.com/capacitor-community/admob/blob/master/ios/Sources/AdMobPlugin/AdMobPlugin.swift#L12-L29

SPMはヘッダーファイルとmファイルを読み込まないので、このように移行しておく必要があります。あと、トップディレクトリに Package.swift が自動生成されます。

3. プラグイン内で新規プラグインをつくる

いろいろ移行方法を考えたのですが、新規プラグインをつくって、 ios フォルダをそのままコピーしてしまうのが一番問題がありません。新規プラグインをつくる方法は以下の通りです。

% cd payment # 今回の例だとpaymentフォルダというプラグインフォルダに移動したものとします
% npm init @capacitor/plugin@latest -- --package-id com.hoge.huga --repo https://example.com --author "hoge" --license MIT --description "hoge" ## プラグイン内にコピーするための新規プラグインをつくります

面倒なので、必要ない項目に関しては適当に入るようにコマンドを調整しています。これをすると、以下の項目を聞かれるので、ちゃんと入れてください。

✔ What should be the npm package of your plugin?
 … 現行のプラグインのnpm名を入力してください
✔ What directory should be used for your plugin?
… プラグインフォルダ名。ここでは `new-template` としましょう。
✔ What should be the class name for your plugin?
… **Plugin.swift の "**" 部分を入力ください。

ちなみにファイル生成したあと npm install が走りますが、別に途中で切ってしまって大丈夫です。

4. iOSフォルダを刷新

さて、構成を刷新していきます。 new-template ディレクトリの使う部分を使い、以前の残すものを残していきます。なお、Web、Androidのコードはここでは変更を行わないので、間違って削除したり上書きしたりしないようにしてください。

4.1. 既存のプラグインコードで new-template を上書き

まず、既存のプラグインコード(ios/plugins の中身)を、 new-template/ios/Sources/**Plugin ディレクトリに移動します。

4.2. new-template/ios フォルダで既存の ios フォルダを上書き

そうするともう不要ですので、既存の ios フォルダを削除できます。今までのプラグインの ios フォルダと随分構造が変わったので、(もちろん不要ファイルを削除してパスの指定をやり直してもいいんですが)、今後を考えてクリーンな形にしましょう。

既存の ios フォルダを削除して、 new-template/ios フォルダをその場所に配置しましょう。

4.4. new-template/Package.swift で、トップディレクトリの Package.swift を上書き

2つめのステップで自動生成された Package.swift ですが、新しくつくったほうで上書きしておきます。これはほとんどの場合において、マイグレーションツールよりも、新規作成の方がクリーンな構成であることが多いためです。

4.5. new-template/package.json で、トップディレクトリの package.json を上書き

package.jsonも、新しくつくったほうで上書きしておきます。npmでリリースするための files の内容が変わっているのと、あと古くから使っているプラグインだとdevDependencyも随分バージョンが変わっていたりします。少なくても、差分で何が変わっているかは確認しておいてください。

4.6 new-template を削除

もう不要ですので、作成した new-template ディレクトリ自体を削除します。

4.7. **.podspec ファイルの更新

podspec ファイルに、iOSのディレクトリ指定があるので、それを以下のように更新します。

- s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'

5. Package.swiftを更新

依存関係がある場合、 Package.swift を更新する必要があります。例えば、 podspec で以下の依存があったとしましょう。

  s.dependency 'StripePaymentSheet', '~> 23.32.0'
  s.dependency 'StripeApplePay', '~> 23.32.0'

その場合、これを Package.swift でも書いておく必要があります。

    dependencies: [
        .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main"),
+       .package(url: "https://github.com/stripe/stripe-ios-spm.git", branch: "main")
    ],
    targets: [
        .target(
            name: "StripePlugin",
            dependencies: [
                .product(name: "Capacitor", package: "capacitor-swift-pm"),
                .product(name: "Cordova", package: "capacitor-swift-pm"),
+               .product(name: "StripePaymentSheet", package: "stripe-ios-spm"),
+               .product(name: "StripeApplePay", package: "stripe-ios-spm")
            ],
            path: "ios/Sources/StripePlugin"),

パッケージマネージャーツールを2つ併用する必要があるため、今後パッケージを管理する上では podspecPackage.swift の両方を更新していく必要があることを覚えておいてください。
これでマイグレーションの終了です!

まとめ

capacitor-plugin-converterがもうちょっといろいろと自動でやってくれると幸せになれるのですが、まぁCapacitorプラグインの構成自体、長い期間にいろいろ試行錯誤されてきたので仕方ない部分もありますよね。フォルダをあっちにコピーしたり、こっちに移動したりとちょっとややこしくみえますが、何をどうマイグレーションするかを先にちゃんと頭にいれておくと単なる単純作業ですので、ぜひチャレンジしてみてください。

それではまた。

Discussion