如何获得 SKProduct 的本地货币 |以 Swift 显示 IAP 价格

How to get Local Currency for SKProduct | Display IAP Price in Swift

我正在尝试使用本地货币显示应用内购买的价格,因此对于美国和加拿大以及欧元、英镑等都显示正确的美元。

我知道每个 SKProduct 都有一个价格,它在交易过程中作为提醒视图出现,在确认购买时出现。

但是我想在确认前显示价格。

我想做这样的事情:

//Products Array
var productsArray: Array<SKProduct!> = []

//Request Products
    func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
        if response.products.count != 0 {
            for product in response.products {
                print("\(product.localizedTitle)")
                productsArray.append(product)
            }
        }
        else {
            print("There are no products.")
        }

        if response.invalidProductIdentifiers.count != 0 {
            print("\(response.invalidProductIdentifiers.description)")
        }            
     }


let item = SKProduct
  for i in productsArray {
    if i.localizedTitle == "com.Company.App.item1" 
      item = i
    }
  }

但这不起作用,因为 i 似乎没有价格 属性。

有人知道如何使用正确的本地货币将标签文本设置为 iAP 的价格吗?

例如£1.49 GBP是$1.99 US dollars using Apples Pricing Matrix并且输出值应该与确认交易时的产品价格值相匹配。

您应该将 NSNumberFormatter 与 price 和 priceLocale 的产品值一起使用,以输出格式正确的字符串,而不管用户位于何处。 product.price returns 作为 NSDecimalNumber 的本地货币价格,以及 product.productLocale returns 价格值的 NSLocale。

例如

var item = SKProduct()
for i in productsArray {
    if i.productIdentifier == "com.Company.App.item1" {
      item = i
      if let formattedPrice = priceStringForProduct(item) {
        //update ui with price
      }
    } 
 }

其中 priceStringForProduct 是在别​​处定义的函数:-

func priceStringForProduct(item: SKProduct) -> String? {
    let numberFormatter = NSNumberFormatter()
    let price = item.price
    let locale = item.priceLocale
    numberFormatter.numberStyle = .CurrencyStyle
    numberFormatter.locale = locale
    return numberFormatter.stringFromNumber(price)
}

您可能还想处理价格为 0.0(免费套餐)的特殊情况。在这种情况下,将 priceStringForProduct 函数修改为:

func priceStringForProduct(item: SKProduct) -> String? {
    let price = item.price
    if price == NSDecimalNumber(float: 0.0) {
        return "GET" //or whatever you like really... maybe 'Free'
    } else {
        let numberFormatter = NSNumberFormatter()
        let locale = item.priceLocale
        numberFormatter.numberStyle = .CurrencyStyle
        numberFormatter.locale = locale
        return numberFormatter.stringFromNumber(price)
    }
}

编辑:结合其他事情,当您指定 productArray 时,更 'Swifty' 的做法是:

var productsArray = [SKProduct]()

然后在您的 didRecieveResponse 中,您可以将 productsArray 设置为 response.products

而不是遍历产品
var productsArray = [SKProduct]()
    if response.products.count != 0 {

        print("\(response.products.map {p -> String in return p.localizedTitle})")
        productsArray = response.products

    }

编辑:为了测试许多不同的语言环境,我通常制作一个 NSLocales 数组,然后循环打印结果。有一个包含所有 localeIdentifiers here

的回购协议

所以:

let testPrice = NSDecimalNumber(float: 1.99)
let localeArray = [NSLocale(localeIdentifier: "uz_Latn"),
    NSLocale(localeIdentifier: "en_BZ"),
    NSLocale(localeIdentifier: "nyn_UG"),
    NSLocale(localeIdentifier: "ebu_KE"),
    NSLocale(localeIdentifier: "en_JM"),
    NSLocale(localeIdentifier: "en_US")]
    /*I got these at random from the link above, pick the countries
    you expect to operate in*/

    for locale in localeArray {
        let numberFormatter = NSNumberFormatter()
        numberFormatter.numberStyle = .CurrencyStyle
        numberFormatter.locale = locale
        print(numberFormatter.stringFromNumber(testPrice))
    }

您不得以当地货币显示价格。您必须以商店提供的货币显示它。如果说法国用户从法国应用商店购买,那么价格就会以欧元计算,这就是用户支付的金额。如果该用户去新西兰并将他或她的区域设置更改为新西兰,但仍留在法国应用商店,他们仍将以欧元计费。所以这就是你应该展示的。

您说“根据 Apple 的定价矩阵,1.49 英镑等于 1.99 美元”。但是 1.49 英镑不是 1.99 美元。如果我作为英国用户去美国并从英国应用商店购买,即使我在美国,我也要支付 1.49 英镑。 “£1.49”是商店会告诉您的。

Swift Olivier 的 3 版本 priceStringForProduct:item

func priceStringForProduct(item: SKProduct) -> String? {
        let price = item.price
        if price == 0 {
            return "Free!" //or whatever you like
        } else {
            let numberFormatter = NumberFormatter()
            let locale = item.priceLocale
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = locale
            return numberFormatter.string(from: price)
        }
    }

StoreKit 编程指南中有这段代码片段用于显示使用 App Store 货币的价格:

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:product.priceLocale];
NSString *formattedPrice = [numberFormatter stringFromNumber:product.price];

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/ShowUI.html 清单 2-3

Swift5和2021版本:

创建 SKProduct 的扩展以便您可以方便地访问 product.localizedPrice

extension SKProduct {

    private static let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        return formatter
    }()

    var isFree: Bool {
        price == 0.00
    }

    var localizedPrice: String? {
        guard !isFree else {
            return nil
        }
        
        let formatter = SKProduct.formatter
        formatter.locale = priceLocale

        return formatter.string(from: price)
    }

}

原答案:

Swift Olivier 的回答 4.2 版本

func priceStringForProduct(item: SKProduct) -> String? {
    let price = item.price
    if price == NSDecimalNumber(decimal: 0.00) {
        return "GET" //or whatever you like really... maybe 'Free'
    } else {
        let numberFormatter = NumberFormatter()
        let locale = item.priceLocale
        numberFormatter.numberStyle = .currency
        numberFormatter.locale = locale
        return numberFormatter.string(from: price)
    }
}

Apple 在此处提供 regularPrice 示例代码:

https://developer.apple.com/documentation/storekit/in-app_purchase/offering_completing_and_restoring_in-app_purchases

extension SKProduct {

    /// - returns: The cost of the product formatted in the local currency.
    var regularPrice: String? {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = self.priceLocale
        return formatter.string(from: self.price)
    }

}

您只需要执行以下操作

product.priceLocale.currencyCode