InApp Покупки локализованная цена фатальная ошибка - PullRequest
0 голосов
/ 12 февраля 2020

Я использую этот код для своих покупок 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. 

Я не понимаю, где находится ошибка. В некоторых случаях этот код работает, но в некоторых случаях он получает фатальную ошибку.

1 Ответ

1 голос
/ 12 февраля 2020

Это

IAPManager.shared.getProducts()

- асинхронный метод, вы не можете получить доступ к массиву продуктов, пока он не будет назван

var callBack:(() -> ())? // 1
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
    self.products = response.products
    products.forEach { print($0.localizedTitle) }
    callBack?() // 2
}

Затем выполните

IAPManager.shared.setupPurchases { success in
    if success {
        print("can make payments")
        IAPManager.shared.callBack = { 
          // now access the products 
        }
        IAPManager.shared.getProducts()
    }
}  

Кстати можно использовать https://github.com/bizz84/SwiftyStoreKit

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...