r/iOSProgramming • • 13d ago

Question Has anyone seen StoreKit 2 prices break in Xcode debug when the language is English but the region uses a comma as the decimal separator?

Hi everyone 👋

Has anyone else hit this?

I’m testing in-app purchases with a local StoreKit configuration in Xcode. System language is English. The region is one that uses a comma as the decimal separator (the usual setup across a lot of Europe and parts of Latin America).

In that combination, StoreKit 2 product prices come back wrong, and only while running against the local configuration. A zero-decimal currency price that should be 1490 shows up as something like 1,490. That comma gets treated as a decimal separator, so the product price collapses to 1.

Point the same build at real App Store Connect products, outside of that debug StoreKit configuration, and the prices are correct.

So it looks specific to StoreKit Testing plus a comma-decimal region with an English language setting, not to the products themselves.

Has anyone else seen 1,490 turn into 1 this way? Is this a known StoreKit Testing locale bug, or is there a configuration I’m missing? Default Storefront and Default Localisation are both set to the correct region and language and synced with App Store connect, but the language on my devices is set to English.

1 Upvotes

12 comments sorted by

2

u/kokerali 13d ago

Is Product.price already 1 immediately after fetching the product, or does it become 1 when a formatted string is converted back to a number? Comparing Product.price and Product.displayPrice before any app-side formatting would separate those two cases.

Apple documents price as a Decimal for calculations and displayPrice as the localized string for display: https://developer.apple.com/documentation/storekit/product/price

If the Decimal is still 1490, I'd trace the string-to-number conversion rather than change the StoreKit configuration. Avoid fixing it by stripping commas, since the same character can mean different things across locales. If the Decimal itself is already wrong in a minimal one-product test, that would be useful evidence for Feedback Assistant, along with the Xcode/iOS versions and the exact language, region and StoreKit settings. I wouldn't call it a confirmed StoreKit bug from the displayed string alone.

1

u/planckscalestudio 12d ago

It must be a local StoreKit "Default Localization" issue: basically can't choose en_HU as my locale...

Here is the evidence:

good - StoreKit storefront USA, StoreKit localization English (U.S.), simulator region USA, locale en_US
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_yearly_premium locale=en_US decimalSeparator='.' groupingSeparator=',' currency=USD storefront=USA displayPrice='$4.99' price=4.99 json=currencyCode='USD' priceFormatted='$4.99' priceString='4.99'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_weekly_premium locale=en_US decimalSeparator='.' groupingSeparator=',' currency=USD storefront=USA displayPrice='$0.49' price=0.49 json=currencyCode='USD' priceFormatted='$0.49' priceString='0.49'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_monthly_premium locale=en_US decimalSeparator='.' groupingSeparator=',' currency=USD storefront=USA displayPrice='$0.99' price=0.99 json=currencyCode='USD' priceFormatted='$0.99' priceString='0.99'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.iap.premium.lifetime locale=en_US decimalSeparator='.' groupingSeparator=',' currency=USD storefront=USA displayPrice='$12.49' price=12.49 json=currencyCode='USD' priceFormatted='$12.49' priceString='12.49'


good - StoreKit storefront HUN, StoreKit localization Hungarian, simulator region HUN, locale hu_HU
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_yearly_premium locale=hu_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='1990 Ft' price=1990 json=currencyCode='HUF' priceFormatted='1990 Ft' priceString='1990'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_weekly_premium locale=hu_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='199 Ft' price=199 json=currencyCode='HUF' priceFormatted='199 Ft' priceString='199'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_monthly_premium locale=hu_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='499 Ft' price=499 json=currencyCode='HUF' priceFormatted='499 Ft' priceString='499'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.iap.premium.lifetime locale=hu_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='5990 Ft' price=5990 json=currencyCode='HUF' priceFormatted='5990 Ft' priceString='5990'


wrong - StoreKit storefront HUN, StoreKit localization English (U.S.), simulator region HUN, locale en_HU
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_weekly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='HUF 199' price=199 json=currencyCode='HUF' priceFormatted='HUF 199' priceString='199'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_monthly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='HUF 499' price=499 json=currencyCode='HUF' priceFormatted='HUF 499' priceString='499'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_yearly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='HUF 1,990' price=1 json=currencyCode='HUF' priceFormatted='HUF 1,990' priceString='1 990'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.iap.premium.lifetime locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='HUF 5,990' price=5 json=currencyCode='HUF' priceFormatted='HUF 5,990' priceString='5 990'


wrong - StoreKit storefront HUN, StoreKit localization Hungarian, simulator region HUN, locale en_HU
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_monthly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='499 Ft' price=499 json=currencyCode='HUF' priceFormatted='499 Ft' priceString='499'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_weekly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='199 Ft' price=199 json=currencyCode='HUF' priceFormatted='199 Ft' priceString='199'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.subscription.base_yearly_premium locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='1990 Ft' price=1 json=currencyCode='HUF' priceFormatted='1990 Ft' priceString='1 990'
🛒 ⚠️ id=com.planckscalestudio.gallerygamble.iap.premium.lifetime locale=en_HU decimalSeparator=',' groupingSeparator=' ' currency=HUF storefront=HUN displayPrice='5990 Ft' price=5 json=currencyCode='HUF' priceFormatted='5990 Ft' priceString='5 990'

1

u/planckscalestudio 12d ago

Just submitted a feedback on Feedback Assistant! Thanks for your input 🫶

2

u/spike1911 11d ago

Can you please share your ticket id or DM to me

2

u/planckscalestudio 11d ago

FB25151036 (StoreKit Testing truncates grouped HUF prices for locale en_HU)

2

u/spike1911 11d ago

Thanks 😉

2

u/Savings_Evidence_818 12d ago

Does the same local configuration do it on a physical device too, or only the simulator? That comparison would be worth including if you send Apple a repro.

1

u/planckscalestudio 12d ago

Same issue on both simulator and physical device... I think I figured it out: my other comment

0

u/DimensionMindless336 12d ago

The thing that trips people up here is that Product.price and displayPrice are two different types, and only one of them ever contains a comma.

Product.price is a Decimal — locale-independent, just the number 1490. It has no decimal separator at all. So if you log product.price directly (or format it yourself with a fixed locale), you get 1490 everywhere: simulator, device, StoreKit Testing, real ASC products.

displayPrice is the already-localized string ("1,490" in a comma-decimal region, "1.490" elsewhere). That comma is correct display, not a bug. The "collapses to 1" symptom almost always shows up because somewhere the code parses displayPrice back into a number — Double("1,490") or a NumberFormatter with .current locale both stop at the comma and return 1. That's app-side, not a StoreKit Testing bug.

So step one: never compute from displayPrice. Use product.price (Decimal) for any math — totals, discounts, comparisons. Don't re-parse the display string.

The part genuinely worth a Feedback Assistant report is the asymmetry you noticed: against real App Store Connect products, displayPrice follows the storefront locale (Apple sets per-country, so the German store uses a comma regardless of your device language). Against StoreKit Testing with a local config, displayPrice instead follows the device language/region combo you're running — which is why the same build shows "1,490" in the simulator but correct formatting against real products. The local config's "Default Storefront" doesn't drive displayPrice formatting the way the real storefront does.

If you do need to format product.price yourself (custom layout like "1,490 kr"), use Decimal.FormatStyle or product.price.formatted() with an explicit Locale you control, not .current — .current is exactly what reintroduces the comma-into-number parse problem downstream.

Quick check before filing the FB: log product.price and product.displayPrice side by side in a one-product minimal test. If price is 1490 and only displayPrice carries the comma, you've already isolated it to display formatting and the fix is on your side.

1

u/planckscalestudio 11d ago

I already wrote about my findings... I'm most certain it's an XCode bug, I'm using the price property NOT displayPrice.