Skip to content

Commit

Permalink
SK2StoreProduct: simplify currencyCode extraction (#2485)
Browse files Browse the repository at this point in the history
I noticed this new property thanks to [this
tweet](https://twitter.com/ariskox/status/1658067009609904129?s=61&t=Zz639sMJdwHISm4AKYXoCw).

This changes the "future" implementation of
`SK2StoreProduct.currencyCode` to use [the new (backdeployed)
property](https://developer.apple.com/documentation/storekit/product/4044347-priceformatstyle).
We still need the existing implementation because `@_backDeploy` won't
work if compiling with `Xcode 13.x`.
  • Loading branch information
NachoSoto committed May 23, 2023
1 parent 4822890 commit c390a66
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
4 changes: 2 additions & 2 deletions Sources/Purchasing/StoreKitAbstractions/SK1StoreProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal struct SK1StoreProduct: StoreProductType {
var price: Decimal { return underlyingSK1Product.price as Decimal }

var localizedPriceString: String {
return priceFormatter?.string(from: underlyingSK1Product.price) ?? ""
return self.priceFormatter?.string(from: underlyingSK1Product.price) ?? ""
}

var productIdentifier: String { return underlyingSK1Product.productIdentifier }
Expand All @@ -59,7 +59,7 @@ internal struct SK1StoreProduct: StoreProductType {
var subscriptionGroupIdentifier: String? { underlyingSK1Product.subscriptionGroupIdentifier }

var priceFormatter: NumberFormatter? {
priceFormatterProvider.priceFormatterForSK1(with: underlyingSK1Product.priceLocale)
return self.priceFormatterProvider.priceFormatterForSK1(with: self.underlyingSK1Product.priceLocale)
}

@available(iOS 11.2, macOS 10.13.2, tvOS 11.2, watchOS 6.2, *)
Expand Down
49 changes: 36 additions & 13 deletions Sources/Purchasing/StoreKitAbstractions/SK2StoreProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,7 @@ internal struct SK2StoreProduct: StoreProductType {

var localizedDescription: String { underlyingSK2Product.description }

var currencyCode: String? {
// note: if we ever need more information from the jsonRepresentation object, we
// should use Codable or another decoding method to clean up this code.
let attributes = jsonDict["attributes"] as? [String: Any]
let offers = attributes?["offers"] as? [[String: Any]]
return offers?.first?["currencyCode"] as? String
}
var currencyCode: String? { self._currencyCode }

var price: Decimal { underlyingSK2Product.price }

Expand All @@ -69,18 +63,14 @@ internal struct SK2StoreProduct: StoreProductType {
Logger.appleError("Can't initialize priceFormatter for SK2 product! Could not find the currency code")
return nil
}
return priceFormatterProvider.priceFormatterForSK2(withCurrencyCode: currencyCode)

return self.priceFormatterProvider.priceFormatterForSK2(withCurrencyCode: currencyCode)
}

var subscriptionGroupIdentifier: String? {
underlyingSK2Product.subscription?.subscriptionGroupID
}

private var jsonDict: [String: Any] {
let decoded = try? JSONSerialization.jsonObject(with: self.underlyingSK2Product.jsonRepresentation, options: [])
return decoded as? [String: Any] ?? [:]
}

var subscriptionPeriod: SubscriptionPeriod? {
guard let skSubscriptionPeriod = underlyingSK2Product.subscription?.subscriptionPeriod else {
return nil
Expand All @@ -100,6 +90,39 @@ internal struct SK2StoreProduct: StoreProductType {

}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
private extension SK2StoreProduct {

var _currencyCode: String? {
#if swift(>=5.7)
if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) {
return self.currencyCodeFromPriceFormat
}
#endif

// note: if we ever need more information from the jsonRepresentation object, we
// should use Codable or another decoding method to clean up this code.
let attributes = jsonDict["attributes"] as? [String: Any]
let offers = attributes?["offers"] as? [[String: Any]]
return offers?.first?["currencyCode"] as? String
}

private var jsonDict: [String: Any] {
let decoded = try? JSONSerialization.jsonObject(with: self.underlyingSK2Product.jsonRepresentation, options: [])
return decoded as? [String: Any] ?? [:]
}

// This is marked as `@_backDeploy`, but it's only visible when compiling with Xcode 14.x
// and for some reason only returning a non-empty string on iOS 16+.
#if swift(>=5.7)
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
private var currencyCodeFromPriceFormat: String {
return self.underlyingSK2Product.priceFormatStyle.currencyCode
}
#endif

}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
extension SK2StoreProduct: Hashable {

Expand Down

0 comments on commit c390a66

Please sign in to comment.