Using a Swift Package Manager (SPM) package in a Capacitor plugin

I’m creating a Capacitor plugin which depends on a 3rd party SDK which is only available via SPM (not Cocoapods).

I’ve done a bit of trial and error with capacitor@5 and capacitor@6-beta but been unable to get it working with SPM.
I’ve tried adding the package manually via Xcode to both the plugin and example app Xcode projects but been unable to get it working so far.

I was able to manually add the package via Xcode to the example proejct for my equivalent Cordova plugin and that works fine.

Since capacitor@6 is in release candidate status, I guess it’s probably worth using it as the basis since it properly supports SPM. I had a look at its SPM and iOS plugin docs but I couldn’t find anything specific about using an SPM package in a Capacitor plugin so I’d appreciate any help as to the correct method to get this working.

Same way the Capacitor 5 plugins where CocoaPods libraries and you add dependencies in the .podspec, in Capacitor 6 they both CocoaPods libraries and swift packages, you would have to add the dependencies in the Package.swift file.
Then depending on your app it will use the CocoaPods library if you created it as a CocoaPods project or the swift package if you created the app as a swift package app.

Note that the SPM support is going to still be beta, even when Capacitor 6 is final.

Thanks @julio-ionic, in my case no Cocoapods version of the library is available so it would be an SPM-only plugin and therefore it would be a requirement for the app project to be created as an SPM app.
I’ll have another go with capacitor@6 when I get some time.

@julio-ionic I had a go at this last evening but not having much success - I can’t even get SPM to work with the official Capacitor plugins:

  • I followed the steps in the v6 documentation.
  • I updated all the latest to next in package.json and npm i
  • But I didn’t bother to add the App plugin since npm init @capacitor/app already contains the Camera plugin and invokes it.
  • I made a slight change to capacitor-welcome.js to display on the page any error which occurs when calling the Camera plugin.

The result, when I build and run the app and press “Take Photo” is the error: “Camera” plugin is not implemented on iOS.
As suggested in the troubleshooting section, I did “Reset Package Caches” and “Resolve Package Versions” in Xcode but this did not fix the problem.

I’ve put this test project here: GitHub - dpa99c/capacitor-spm-test

My environment details:

  • MacOS v13.5.1
  • Xcode v15.2
  • Node v20.10.0
  • @capacitor/cli v6.0.0-rc.0
  • Test device: iPhone 11 / iOS 17.4 Beta 3

Any help much appreciated

There seems to be a problem on the Package.swift file generation, it’s adding correctly the plugin dependencies in the dependencies section, but missing the dependencies in the targets section.

For now you could workaround it by adding this to the Package.swift manually

.product(name: "CameraPlugin", package: "CapacitorCamera"),
.product(name: "SplashScreenPlugin", package: "CapacitorSplashScreen"),

right after the .product(name: "Cordova", package: "capacitor6-spm-test"),.

We are working on a fix at the moment, should be included in next RC release or on the final release.

Thanks for the quick response - I’ll give this a try.

I had a look at this over the weekend:

It looks like the dependencies are being added correctly to ios/App/CapApp-SPM/Package.swift so this is not the cause of the problem.
It should be easy enough to reproduce so hopefully it’s an easy find+fix for your team.
Meantime I’ll put my Capacitor plugin implementation on hold awaiting resolution of this issue and move onto the React Native module.

No, they are not added correctly, they also have to be added to the targets section and in a different way, notice that the text I told you to add is different from the text you already have.

Yep, you are correct, I did not RTFM: adding the dependencies to targets and npx cap sync ios worked and the plugins are now detected. Thanks for your help.

Is there a way of making this work using the Cocoapods version of the plugin (Capacitor 5)? I tried the Capacitor 6 version, the plugin is recognised (after manually adding the entries to the targets section of Package.swift), but when I try to actually run it on the device, I get the “not implemented” error. Besides that, it seems that not all plugins are SPM ready (for example: capacitor-plugins/google-maps at main · ionic-team/capacitor-plugins · GitHub), so that makes Capacitor6 incompatible with my app.

I tried manually adding the dependency from XCode but it’s still not recognised. I get the “No such module” error, even though the dependency is available in the “Package dependencies” tab.

Any kind of help with making this work in Capacitor 5 would be greatly appreciated.
Thank you!

You can’t make it work in Capacitor 5, this is a Capacitor 6 feature. There will be soon a new Capacitor 6 RC release with the issues fixed.

Google maps plugin will be updated once google-maps-ios-utils dependency gets updated to use Google Maps SDK 8, which is the first one in supporting SPM, so we don’t know when that will happen since it’s a Google project.