Я использую этот код для своих покупок inApp, чтобы показать локализованную цену:
private func priceStringFor(product: SKProduct) -> String {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
numberFormatter.locale = product.priceLocale
return numberFormatter.string(from: product.price)!
}
override func viewDidLoad() {
super.viewDidLoad()
perYearPrice.setTitle("\(priceStringFor(product: IAPManager.shared.products[1])) per year", for: .normal)
oneTimePrice.setTitle("\(priceStringFor(product: IAPManager.shared.products[0])) one time", for: .normal)
}
И это мой код IAPManager:
import Foundation
import StoreKit
class IAPManager: NSObject {
static let shared = IAPManager()
private override init() {}
var products: [SKProduct] = []
let paymentQueue = SKPaymentQueue.default()
public func setupPurchases(callback: @escaping(Bool) -> ()) {
if SKPaymentQueue.canMakePayments() {
paymentQueue.add(self)
callback(true)
return
}
callback(false)
}
public func getProducts() {
let identifiers: Set = ["inapp1", "inapp2"]
let productRequest = SKProductsRequest(productIdentifiers: identifiers)
productRequest.delegate = self
productRequest.start()
}
public func purchase(productWith identifier: String) {
guard let product = products.filter({ $0.productIdentifier == identifier }).first else { return }
let payment = SKPayment(product: product)
paymentQueue.add(payment)
}
public func restoreCompletedTransactions() {
paymentQueue.restoreCompletedTransactions()
}
}
extension IAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .deferred: break
case .purchasing: break
case .failed: failed(transaction: transaction)
case .purchased: completed(transaction: transaction)
case .restored: restored(transaction: transaction)
@unknown default: fatalError()
}
}
}
func purchased() {
let adRemovalPurchased = UserDefaults.standard
adRemovalPurchased.set(true, forKey: "adRemoved")
adRemovalPurchased.synchronize()
}
private func failed(transaction: SKPaymentTransaction) {
if let transactionError = transaction.error as NSError? {
if transactionError.code != SKError.paymentCancelled.rawValue {
print("Error: \(transaction.error!.localizedDescription)")
}
}
paymentQueue.finishTransaction(transaction)
}
private func completed(transaction: SKPaymentTransaction) {
paymentQueue.finishTransaction(transaction)
purchased()
}
private func restored(transaction: SKPaymentTransaction) {
paymentQueue.finishTransaction(transaction)
purchased()
}
}
extension IAPManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
products.forEach { print($0.localizedTitle) }
}
}
Также я поместил этот код в AppDelegate :
IAPManager.shared.setupPurchases { success in
if success {
print("can make payments")
IAPManager.shared.getProducts()
}
}
Но когда я пытаюсь получить локализованную цену для IAPManager.shared.products [1]), я получаю
Fatal error: Index out of range.
Я не понимаю, где находится ошибка. В некоторых случаях этот код работает, но в некоторых случаях он получает фатальную ошибку.