JKSDEV JKSDEV - 7 months ago 179
Swift Question

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

I am trying to display the price of an in app purchase using the local currency, so the correct dollar is displayed for both US & CA as well as Euro, GBP etc.

I know each SKProduct has a price which appears during the transaction as an alert view, this appears when confirming the purchase.

However I want to display the price before confirmation.

I was thinking to do something like this:

//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
}
}


But this doesn't work as
i
Doesn't seem to have a price property.

Does anybody know how I can set a label text to the price of an iAP using the correct local currency?

For example £1.49 GBP is $1.99 US dollars using Apples Pricing Matrix and outputting the value should match the values of the product price when confirming the transaction.

Answer

you should use NSNumberFormatter with the product values for price and priceLocale to output a string that is formatted correctly regardless of the user's location. product.price returns the price in the local currency as an NSDecimalNumber, and product.productLocale returns the NSLocale for the price value.

eg

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

where priceStringForProduct is function defined elsewhere:-

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

You might also want to handle the special case where the price is 0.0 (free tier). In this case amend the priceStringForProduct function to:

func priceStringForProduct(item: SKProduct) -> String? {
    let price = product.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)
    }
}

Edit: Couple other things, when you specify your productArray a more 'Swifty' way of doing it is:

var productsArray = [SKProduct]()

and then in your didRecieveResponse, instead of looping through the products you can just set productsArray as response.products

var productsArray = [SKProduct]()
    if response.products.count != 0 {

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

    }