Как получить местную валюту для SKProduct | Показать цену IAP в Swift

Я пытаюсь отобразить цену покупки приложения в местной валюте, поэтому правильный доллар отображается как для США, так и для США, а также для евро, GBP и т.д.

Я знаю, что каждый 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 доллара США, используя матрицу ценообразования на основе яблок, и вывод значения должен соответствовать значениям цены продукта при подтверждении транзакции.

Ответ 1

Swift 5 и версия 2019:

Создание расширения для SKProduct, чтобы вы могли получить к нему удобный доступ, например, вот так: fetchedProduct.localizedPrice. Вот код

extension SKProduct {
    fileprivate static var formatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        return formatter
    }

    var localizedPrice: String {
        if self.price == 0.00 {
            return "Get"
        } else {
            let formatter = SKProduct.formatter
            formatter.locale = self.priceLocale

            guard let formattedPrice = formatter.string(from: self.price)else {
                return "Unknown Price"
            }

            return formattedPrice
        }
    }
}

Оригинальный Anser:

Swift 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)
    }
}

Ответ 2

вы должны использовать NSNumberFormatter с значениями продукта для цены и priceLocale для вывода строки, которая отформатирована правильно независимо от местоположения пользователя. product.price возвращает цену в местной валюте как NSDecimalNumber, а product.productLocale возвращает 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)
    }
}

Изменить: добавьте другие вещи, когда вы укажете свой товарный массив более "быстрым" способом:

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 здесь

так:

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

Ответ 3

В Руководстве по программированию 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

Ответ 4

Вы НЕ ДОЛЖНЫ отображать цену в местной валюте. Вы должны отобразить его в валюте, предоставляемой магазином. Если сказать, что французский пользователь покупает у французского магазина приложений, тогда цена появляется в евро, и это то, что платит пользователь. Если этот пользователь отправляется в Новую Зеландию и изменяет свой язык в Новую Зеландию, но остается с французским магазином приложений, они по-прежнему оплачиваются в евро. Итак, что вы должны отображать.

Вы говорите: "1,49 фунта стерлингов составляет 1,99 доллара США в соответствии с матрицей ценообразования Apple". Но 1,49 фунта не 1,99 доллара. Если я, как британский пользователь, отправляюсь в США и покупаю из магазина приложений в Великобритании, я плачу 1,49 фунта стерлингов, даже если я в США. И "£ 1.49" - это то, что расскажет вам магазин.

Ответ 5

Свифт 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)
        }
    }