Skip to content

fix(apple): add iOS 15 compatibility for priceFormatStyle API#80

Merged
hyochan merged 4 commits intomainfrom
fix/apple-storekit2-availability
Feb 12, 2026
Merged

fix(apple): add iOS 15 compatibility for priceFormatStyle API#80
hyochan merged 4 commits intomainfrom
fix/apple-storekit2-availability

Conversation

@hyochan
Copy link
Member

@hyochan hyochan commented Feb 12, 2026

Summary

  • Fix potential crash on iOS 15 devices when using priceFormatStyle.currencyCode
  • Unify @available annotations across all Swift files
  • Add Apple documentation links for better code navigation

Changes

StoreKit 2 iOS 15 Compatibility

  • Add currencyCode(from:) helper function with #available(iOS 16.0, ...) check
  • Fall back to Locale.current.currencyCode on iOS 15
  • Prevents crash when running on iOS 15 devices with deployment target < iOS 16

@available Annotation Unification

  • All files now use: @available(iOS 15.0, macOS 14.0, tvOS 16.0, watchOS 8.0, *)
  • Fixed macOS version inconsistency: 12.014.0 (matches podspec)
  • Added explicit tvOS and watchOS versions

Documentation Links

Added Apple Developer documentation SeeAlso links:

  • ProductManager/storekit/product
  • IapState/storekit/transaction
  • StoreKitTypesBridge/storekit/product
  • OpenIapModule/storekit/in-app_purchase
  • OpenIapStore/storekit/in-app_purchase
  • OpenIapProtocol/storekit/transaction
  • OpenIapSerialization/storekit

Test plan

  • swift build passes
  • No errors, only expected warning about macOS version check

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Extended platform support to Apple TV (tvOS 16.0) and Apple Watch (watchOS 8.0)
  • Documentation

    • Added comprehensive platform availability documentation and StoreKit references
    • Improved currency code handling with automatic fallback support for older OS versions
  • Refactor

    • Updated macOS minimum deployment target to 14.0 for enhanced compatibility

hyochan and others added 2 commits February 12, 2026 12:19
- Add currencyCode() helper with #available check for iOS 16+
- Fall back to Locale.current.currencyCode on iOS 15
- Unify @available annotations with tvOS 16.0, watchOS 8.0
- Fix macOS version inconsistency (12.0 → 14.0) in some files
- Add Apple documentation SeeAlso links to all main types

This ensures StoreKit 2 works correctly on iOS 15 devices where
priceFormatStyle.currencyCode could cause crashes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add s.watchos.deployment_target = '8.0' to match Package.swift

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

Warning

Rate limit exceeded

@hyochan has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 47 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

The PR expands Apple platform support by adding tvOS 16.0 and watchOS 8.0 availability annotations across multiple framework files, introduces a new currencyCode(from:) helper method in StoreKitTypesBridge with fallback logic for older OS versions, and updates the podspec deployment targets. Documentation references are added via SeeAlso annotations.

Changes

Cohort / File(s) Summary
Platform Availability Expansion
packages/apple/Sources/Helpers/IapState.swift, packages/apple/Sources/Helpers/ProductManager.swift, packages/apple/Sources/Models/OpenIapSerialization.swift, packages/apple/Sources/OpenIapModule+ObjC.swift, packages/apple/Sources/OpenIapModule.swift, packages/apple/Sources/OpenIapProtocol.swift, packages/apple/Sources/OpenIapStore.swift
Extended @available attributes to include tvOS 16.0 and watchOS 8.0 alongside existing iOS/macOS versions; added SeeAlso documentation references to Apple StoreKit documentation.
Currency Code Helper & Integration
packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
Added new currencyCode(from product:) static helper method with iOS 16+ API usage and fallback to Locale.currencyCode; updated productIOS and productSubscriptionIOS call sites to use the new helper; expanded availability attributes to include tvOS 16.0 and watchOS 8.0.
Deployment Target Update
packages/apple/openiap.podspec
Added watchOS 8.0 deployment target specification to the CocoaPods podspec configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #26: Adds tvOS deployment target to podspec, parallel to watchOS target addition in this PR.
  • #21: Modifies StoreKitTypesBridge with new helper functions and product conversion updates, directly related to the currency code helper changes.
  • #76: Updates availability annotations across Apple framework files, overlapping with the platform support expansion in this PR.

Suggested labels

🛠 enhancement, 📦 dependencies, 🍎 Apple

Poem

🐰 A watchful rabbit hops through tvOS lands,
With currency codes held in gentle hands,
From iOS gleams to macOS' gentle glow,
Eight platforms strong, the openiap tree does grow! 🌳✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title references 'iOS 15 compatibility for priceFormatStyle API', but the PR's main focus is to add tvOS 16.0 and watchOS 8.0 support across multiple platform declarations and fix macOS version inconsistencies (12.0 → 14.0), not iOS 15 compatibility. Revise the title to reflect the primary change: something like 'fix(apple): extend Apple platform support (tvOS, watchOS) and unify availability annotations' or 'fix(apple): add tvOS 16.0 and watchOS 8.0 support with iOS 15 compatibility fallback'.
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/apple-storekit2-availability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @hyochan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the stability and maintainability of the Apple In-App Purchase (IAP) module by introducing backward compatibility for price formatting on iOS 15, standardizing API availability declarations across multiple platforms, and improving developer experience through integrated documentation links.

Highlights

  • iOS 15 Compatibility for Price Formatting: Implemented a new helper function, currencyCode(from:), to safely retrieve currency codes from StoreKit products. This prevents potential crashes on iOS 15 devices by falling back to Locale.current.currencyCode when the iOS 16+ priceFormatStyle.currencyCode API is unavailable.
  • Unified @available Annotations: Standardized @available annotations across all Swift files to ensure consistent API availability declarations for iOS (15.0), macOS (14.0), tvOS (16.0), and watchOS (8.0). This included correcting a macOS version inconsistency from 12.0 to 14.0.
  • Enhanced Documentation Links: Added SeeAlso documentation links to various classes and protocols, pointing directly to relevant Apple Developer documentation pages for StoreKit, improving code navigation and understanding.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • packages/apple/Sources/Helpers/IapState.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0, and corrected macOS version to 14.0.
    • Added a documentation link to the StoreKit Transaction page.
  • packages/apple/Sources/Helpers/ProductManager.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0, and corrected macOS version from 12.0 to 14.0.
    • Added a documentation link to the StoreKit Product page.
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0.
    • Added a documentation link to the StoreKit Product page.
    • Introduced a new currencyCode(from:) static helper function to provide iOS 15 compatibility for retrieving currency codes.
    • Replaced direct product.priceFormatStyle.currencyCode calls with the new currencyCode(from:) helper in product and subscription initializers.
    • Updated @available annotations for private extensions within the file.
  • packages/apple/Sources/Models/OpenIapSerialization.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0, and corrected macOS version from 12.0 to 14.0.
    • Added a documentation link to the main StoreKit page.
  • packages/apple/Sources/OpenIapModule+ObjC.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0.
    • Added a documentation link to the StoreKit In-App Purchase page.
  • packages/apple/Sources/OpenIapModule.swift
    • Updated @available annotation to include tvOS 16.0 and watchOS 8.0.
    • Added a documentation link to the StoreKit In-App Purchase page.
    • Integrated the StoreKitTypesBridge.currencyCode(from:) helper for non-renewing subscription currency retrieval.
  • packages/apple/Sources/OpenIapProtocol.swift
    • Updated @available annotations for PurchaseUpdatedListener, PurchaseErrorListener, PromotedProductListener, and OpenIapModuleProtocol to include tvOS 16.0 and watchOS 8.0.
    • Added documentation links to the StoreKit Transaction and In-App Purchase pages.
  • packages/apple/Sources/OpenIapStore.swift
    • Updated @available annotations for the OpenIapStore class and its private extensions to include tvOS 16.0 and watchOS 8.0.
    • Added a documentation link to the StoreKit In-App Purchase page.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a potential crash on iOS 15 by introducing a compatibility helper for priceFormatStyle.currencyCode. The changes also improve code consistency by unifying @available annotations and enhance documentation with links to Apple's official resources. I've suggested one improvement to the iOS 15 fallback logic to make it more accurate by using the product's locale instead of the device's current locale, which could differ from the App Store storefront currency.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/apple/openiap.podspec (1)

19-22: ⚠️ Potential issue | 🟡 Minor

Description doesn't mention watchOS.

Now that watchOS is a supported platform, consider updating the description to include it.

Proposed fix
   s.description      = <<-DESC
-    OpenIAP is a modern Swift library for handling in-app purchases using StoreKit 2.
-    Supports iOS, macOS, and tvOS with a simple and intuitive API.
+    OpenIAP is a modern Swift library for handling in-app purchases using StoreKit 2.
+    Supports iOS, macOS, tvOS, and watchOS with a simple and intuitive API.
   DESC
🧹 Nitpick comments (2)
packages/apple/Sources/Helpers/StoreKitTypesBridge.swift (1)

507-514: iOS 15 fallback returns device locale currency, not the product's currency.

Locale.current.currencyCode returns the currency for the user's device locale, which may differ from the product's actual currency (e.g., a user with US locale buying from a JP storefront). This is a known limitation and an acceptable tradeoff for iOS 15 where priceFormatStyle.currencyCode isn't available, but it would be helpful to document this caveat inline.

Also, Locale.current.currencyCode is deprecated starting iOS 16 / macOS 13. Since this code path is only reachable on older OS versions (guarded by #available), it won't cause runtime issues, but it may trigger a compile-time deprecation warning.

📝 Suggested inline documentation
     static func currencyCode(from product: StoreKit.Product) -> String? {
         if `#available`(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) {
             return product.priceFormatStyle.currencyCode
         } else {
-            // iOS 15 fallback - use locale's currency
+            // iOS 15 fallback - uses device locale's currency, which may differ from the
+            // product's actual currency. This is the best approximation available on iOS 15
+            // where priceFormatStyle.currencyCode doesn't exist.
             return Locale.current.currencyCode
         }
     }
packages/apple/Sources/OpenIapStore.swift (1)

417-418: Pre-existing: getAppTransactionIOS availability is narrower than its implementation.

Not introduced by this PR, but worth noting: OpenIapStore.getAppTransactionIOS() has @available(iOS 16.0, macOS 14.0, *) (missing tvOS/watchOS), while its implementation in OpenIapModule.swift (Line 827) has @available(iOS 16.0, macOS 14.0, tvOS 16.0, watchOS 9.0, *). The same gap exists in OpenIapModule+ObjC.swift (Line 606). Consider aligning these in a follow-up.

hyochan and others added 2 commits February 12, 2026 12:26
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use product.priceFormatStyle.locale.currencyCode instead of
Locale.current.currencyCode to get the correct App Store currency
rather than the device's locale currency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hyochan hyochan merged commit fa4dfe4 into main Feb 12, 2026
7 checks passed
@hyochan hyochan deleted the fix/apple-storekit2-availability branch February 12, 2026 03:30
hyochan added a commit that referenced this pull request Feb 12, 2026
## Summary

- Use `#if os(iOS) || os(tvOS)` instead of `canImport(UIKit)` for
UIWindowScene (not available on watchOS)
- Use `#if os(iOS)` for `presentCodeRedemptionSheet` (iOS-only API)
- Use `#if os(iOS) || os(tvOS) || os(visionOS)` for `UIApplication.open`
(not available on watchOS/macOS)
- Add `watchOS 9.0` to `@available` for `getAppTransactionIOS`
(AppTransaction requires watchOS 9.0+)
- Add `tvOS 16.0` to `@available` annotations for consistency

Fixes watchOS build errors that occurred after merging #80.

## Test plan

- [x] Validated with `pod lib lint openiap.podspec --allow-warnings`
- [ ] CI build passes for all platforms (iOS, macOS, tvOS, watchOS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added support for tvOS 16.0 and watchOS 9.0 platforms.

* **Improvements**
* Enhanced platform detection logic across Apple devices for better
compatibility.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant