我正在尝试在我正在创建的应用程序中实现应用内购买,但是当我尝试“获取”产品时,我有 var products = [SKProducts]()
但这会返回一个空数组导致应用程序崩溃。
我已经检查了所有税务协议(protocol)等,当我在应用程序购买示例项目中的苹果中进行测试时,IAP 就会出现。
出现问题的完整代码如下。
class Model {
var products = [SKProduct]()
func getProduct(containing keyword: String) -> SKProduct? {
// print("The array of SKProducts in Model getProduct is \(products)")
// let test = products.filter { $0.productIdentifier.contains(keyword) }.first
print("The products are: \(products)")
print(products.filter { $0.productIdentifier.contains(keyword) }.first)
return products.filter { $0.productIdentifier.contains(keyword) }.first
}
}
打印语句返回: “产品是:[]”和 “无”
如果有帮助,可以在 GitHub 上找到完整的项目 here
最佳答案
函数getProduct
除了打印一个空数组(products
),并过滤这个空数组并检索第一个元素(不存在)之外什么也不做。 .
我建议使用这样的助手(我从某处复制它,不记得在哪里):
import Foundation
import StoreKit
class IAPHelper: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
typealias RequestProductsCompletionHandler = (_ success:Bool, _ products:[SKProduct]?) -> ()
var completionHandler: RequestProductsCompletionHandler?
var productsRequest: SKProductsRequest?
var productIdentifiers: Set<String>
var purchasedProductIdentifiers: Set<String>?
// MARK: - Init
init(identifiers: Set<String>) {
// Store product identifiers
productIdentifiers = identifiers;
// Check for previously purchased products
purchasedProductIdentifiers = Set()
for productIdentifier in productIdentifiers {
let productPurchased = UserDefaults.standard.bool(forKey: productIdentifier)
if productPurchased {
purchasedProductIdentifiers?.insert(productIdentifier)
print("Previously purchased: \(productIdentifier)");
} else {
print("Not purchased: \(productIdentifier)");
}
}
super.init() // must be called after subclass init, but before "self" is used
SKPaymentQueue.default().add(self)
} // init
func requestProductsWithCompletionHandler(_ completionHandler: @escaping RequestProductsCompletionHandler) {
self.completionHandler = completionHandler
productsRequest = SKProductsRequest.init(productIdentifiers: productIdentifiers)
productsRequest!.delegate = self
productsRequest!.start()
}
// MARK: - Products request delegate
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
productsRequest = nil
let skProducts = response.products
for skProduct in skProducts {
print("Found product: \(skProduct.productIdentifier), \(skProduct.localizedTitle), \(skProduct.price.floatValue)");
}
completionHandler!(true, skProducts)
completionHandler = nil
}
func request(_ request: SKRequest, didFailWithError error: Error) {
// NOTE: If this happens on the simulator, close the simulator window and re-run the app. This helps normally !!!
print("Failed to load list of products. Error: \(error)")
productsRequest = nil
completionHandler!(false, nil)
completionHandler = nil
}
// MARK: - Purchase
func productPurchchased(_ productIdentifier:String) -> Bool {
return purchasedProductIdentifiers!.contains(productIdentifier)
}
func buyProduct(_ product:SKProduct) {
print("Buying \(product.productIdentifier)");
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case SKPaymentTransactionState.purchased:
self.completeTransaction(transaction)
case SKPaymentTransactionState.failed:
self.failedTransaction(transaction)
case SKPaymentTransactionState.restored:
self.restoreTransaction(transaction)
default:
print("Error: Unknown SKPaymentTransactionState")
}
}
}
func completeTransaction(_ transaction:SKPaymentTransaction) {
print("completeTransaction...");
self.provideContentForProductIdentifier(transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}
func restoreTransaction(_ transaction:SKPaymentTransaction) {
print("restoreTransaction...");
self.provideContentForProductIdentifier(transaction.original!.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}
func failedTransaction(_ transaction:SKPaymentTransaction) {
print("failedTransaction...");
if let error = transaction.error as NSError?, error.code == SKError.paymentCancelled.rawValue {
print("Transaction error:\(error.localizedDescription)");
}
SKPaymentQueue.default().finishTransaction(transaction)
}
func provideContentForProductIdentifier(_ productIdentifier:String) {
purchasedProductIdentifiers?.insert(productIdentifier)
UserDefaults.standard.set(true, forKey:productIdentifier)
NotificationCenter.default.post(name: Notification.Name(rawValue: IAPHelperProductPurchasedNotification), object: productIdentifier, userInfo: nil)
}
func restoreCompletedTransactions() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
}
关于ios - Swift 中 SKProduct() 的应用内购买问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59707043/