Skip to content

Commit 8dd4d57

Browse files
committed
docs: update troubleshooting and contributing with Xcode 26 findings
The SPM issue was not a fundamental Swift limitation — it's that Capacitor 8's xcframework requires Xcode 26 ($NonescapableTypes). Update docs to reflect the correct diagnosis and CI matrix.
1 parent a1f5149 commit 8dd4d57

2 files changed

Lines changed: 17 additions & 25 deletions

File tree

capacitor/CONTRIBUTING.md

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,25 @@ The plugin targets iOS 15.0 but some APIs require newer versions:
2424

2525
Always wrap these in availability checks with a fallback.
2626

27-
## SPM (Swift Package Manager) compatibility
27+
## SPM and Xcode version requirements
2828

29-
The plugin builds with CocoaPods. SPM support is provided via `Package.swift` but has known limitations with Capacitor's precompiled xcframework.
29+
Capacitor 8 defaults to SPM and distributes its iOS framework as a precompiled `.xcframework` via `capacitor-swift-pm`. The xcframework is compiled with **Xcode 26** (Swift 6.2+), which enables `$NonescapableTypes` by default. The `.swiftinterface` files gate extension methods (`reject()`, `getString()`, `getBool()`, etc.) behind this compiler feature flag.
3030

31-
### The problem
31+
**This means Capacitor 8 + SPM requires Xcode 26.** With the correct Xcode version, all APIs work natively — no workarounds needed. Use idiomatic Capacitor APIs in the plugin code.
3232

33-
Capacitor distributes its iOS framework as a precompiled `.xcframework` via `capacitor-swift-pm`. Swift extension methods on Objective-C types are not exported from binary frameworks. This means common Capacitor APIs are invisible when built via SPM:
33+
Capacitor 6 and 7 use CocoaPods by default, which compiles from source. Any Xcode version that supports the deployment target (15.0) works.
3434

35-
| API | SPM status | Workaround |
36-
|-----|-----------|------------|
37-
| `call.resolve()` | Works | (zero-arg overload) |
38-
| `call.resolve(data)` | Works | |
39-
| `call.reject(msg)` | Not available | None reliable — method is invisible |
40-
| `call.getString("key")` | Not available | `call.options["key"] as? String` |
41-
| `call.getArray("key")` | Not available | `call.options["key"] as? [Type]` |
42-
| `call.getBool("key")` | Not available | `call.getBool("key", false)` |
43-
| `CAPPluginCallError(...)` | Not available | Init is inaccessible |
35+
## CI matrix
4436

45-
### Impact
46-
47-
This is a Capacitor-level issue affecting **all** third-party plugins, not specific to this one. It needs to be resolved upstream in `ionic-team/capacitor` by either shipping source via SPM instead of precompiled binaries, or moving APIs to ObjC headers. SPM became the default in Capacitor 8.
48-
49-
### CI strategy
50-
51-
The CI tests against Capacitor 6 and 7 using CocoaPods (the default for those versions). Once the upstream SPM issue is resolved, Capacitor 8 can be added to the test matrix.
37+
| Capacitor | Runner | Xcode | Package Manager |
38+
|-----------|----------|-------|-----------------|
39+
| 6 | macOS-14 | 15.4 | CocoaPods |
40+
| 7 | macOS-14 | 15.4 | CocoaPods |
41+
| 8 | macOS-15 | 26.0 | SPM |
5242

5343
## CI environment notes
5444

55-
- **macOS-15 + Xcode 16.2** may report "no destinations" with `-sdk iphoneos`. Use `-destination 'generic/platform=iOS'` instead.
45+
- **macOS-15 + Xcode 16.2** fails with "iOS 18.2 Platform Not Installed" on storyboard compilation. Use Xcode 26 (for Cap 8) or macOS-14 + Xcode 15.4 (for Cap 6/7).
5646
- **`@capacitor/create-app`** always scaffolds the latest template (Cap 8 / SPM) regardless of CLI version. For testing older versions, scaffold manually with `npm init` + pinned deps.
47+
- **Podfile deployment target**: Cap 6/7 generate Podfiles defaulting to iOS 13.0/14.0. The plugin needs 15.0 — CI patches this with `sed`.
5748
- **Ruby version conflicts** on macOS: `pod` (Homebrew) and `gem` (system) may point to different Ruby versions. Install gems with the Homebrew Ruby if needed.

capacitor/TROUBLESHOOTING.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@ To test on your Mac without a physical device:
3131

3232
This works for testing the purchase flow with sandbox accounts.
3333

34-
## Capacitor 8 / SPM support
34+
## Capacitor 8 / SPM requires Xcode 26
3535

36-
Capacitor 8 defaults to Swift Package Manager (SPM). There is a known upstream issue where the Capacitor precompiled xcframework does not export certain Swift extension methods to plugins. This affects all third-party Capacitor plugins, not just this one.
36+
Capacitor 8 defaults to Swift Package Manager (SPM). The Capacitor xcframework is compiled with Xcode 26 (Swift 6.2+), so **you need Xcode 26 or later** to build.
3737

38-
**If you hit build errors with Capacitor 8**, use CocoaPods instead:
38+
If you see errors like `value of type 'CAPPluginCall' has no member 'reject'`, your Xcode is too old. Update to Xcode 26+.
39+
40+
As a fallback, you can use CocoaPods instead:
3941

4042
```bash
41-
# Remove the iOS project and recreate with CocoaPods
4243
rm -rf ios
4344
npx cap add ios --packagemanager CocoaPods
4445
npx cap sync ios

0 commit comments

Comments
 (0)