我经历了this tutorial,并开始进行应用购买。这个例子就是这个教程比我需要的要复杂得多。
我试图创建一个具有两个按钮的类似程序,只有当您拥有该应用程序的“高级”版本时,才能单击on按钮。在购买之前,该按钮会被另一个标有溢价的按钮覆盖]
一旦购买了唯一的一种产品,高级标签就会消失。溢价标签是一个开始付款过程的按钮。
我有两个主要问题。
在我的MasterViewControllerClass中,我不知道如何购买产品,因为我只知道产品标识符,所以我不知道在Premium.store.buyProduct(<#T##product: SKProduct##SKProduct#>)
行中输入什么内容>
@IBAction func buyPremium(_ sender: UIButton) { if Premium.store.isProductPurchased(self.productIdentifier){ Premium.store.restorePurchases() }else if IAPHelper.canMakePayments(){ Premium.store.buyProduct(<#T##product: SKProduct##SKProduct#>) }else{ let alert = UIAlertController(title: "Not authorized to make payments", message: "You can not make purchases on this device", preferredStyle: .alert) let ok = UIAlertAction(title: "OK", style: .default, handler: nil) alert.addAction(ok) self.present(alert, animated: true, completion: nil) } } }
[下一步,我没有对文件IAPHelper.swift进行任何更改。老实说,我真的不知道该文件中发生了什么,但这也许不是问题吗?我不确定。
IAPHelper.swift
import StoreKit public typealias ProductIdentifier = String public typealias ProductsRequestCompletionHandler = (_ success: Bool, _ products: [SKProduct]?) -> Void extension Notification.Name { static let IAPHelperPurchaseNotification = Notification.Name("IAPHelperPurchaseNotification") } open class IAPHelper: NSObject { private let productIdentifiers: Set<ProductIdentifier> private var purchasedProductIdentifiers: Set<ProductIdentifier> = [] //Tracks which items have been purchased private var productsRequest: SKProductsRequest? //Used by SKProductsRequest to perform requests to Apple private var productsRequestCompletionHandler: ProductsRequestCompletionHandler? //Used by SKProductsRequest to perform requests to Apple public init(productIds: Set<ProductIdentifier>) { productIdentifiers = productIds for productIdentifier in productIds { //For each product identifier you check whether it's stored in UserDefaults let purchased = UserDefaults.standard.bool(forKey: productIdentifier) if purchased { //If it is you insert that identifier into the purchasedProductIdentifiers set purchasedProductIdentifiers.insert(productIdentifier) print("Previously purchased: \(productIdentifier)") } else { print("Not purchased: \(productIdentifier)") } } super.init() SKPaymentQueue.default().add(self) } } // MARK: - StoreKit API extension IAPHelper: SKProductsRequestDelegate { //Called when list is successfully retrieved //Receives an array of SKProduct objects and passes them to previously saved completion handler //Handler reloads table with new data //request(_:didFailWithError:) is called if a problem occurs //when the request finishes, both the request and completion handler are cleared with clearRequestAndHandler() public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print("Loaded list of products...") let products = response.products productsRequestCompletionHandler?(true, products) clearRequestAndHandler() for p in products { print("Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)") } } public func request(_ request: SKRequest, didFailWithError error: Error) { print("Failed to load list of products.") print("Error: \(error.localizedDescription)") productsRequestCompletionHandler?(false, nil) clearRequestAndHandler() } private func clearRequestAndHandler() { productsRequest = nil productsRequestCompletionHandler = nil } /** */ public func requestProducts(completionHandler: @escaping ProductsRequestCompletionHandler) { productsRequest?.cancel() productsRequestCompletionHandler = completionHandler //save user's completion handler for future execution productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers) //Create and initialize a request to apple productsRequest!.delegate = self productsRequest!.start() } public func buyProduct(_ product: SKProduct) { let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) } //Checks locally if product is purchased, to avoid making requests to apples servers every time public func isProductPurchased(_ productIdentifier: ProductIdentifier) -> Bool { return purchasedProductIdentifiers.contains(productIdentifier) } public class func canMakePayments() -> Bool { return SKPaymentQueue.canMakePayments() } public func restorePurchases() { SKPaymentQueue.default().restoreCompletedTransactions() } } extension IAPHelper: SKPaymentTransactionObserver { /** Delegate method Gets Called when one or more transaction states change Evaluates the state of each transaction in an array of updated transactions Calls the relevant helper method (complete(transaction)), restore(transaction), or fail(transaction)) */ public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchased: complete(transaction: transaction) break case .failed: fail(transaction: transaction) break case .restored: restore(transaction: transaction) break case .deferred: break case .purchasing: break } } } /** Adds to the set of purchases and saves the identifier in UserDefaults Also posts a notification with that transaction so any interested object in the app can listen for it to do things like update the user interface */ private func complete(transaction: SKPaymentTransaction) { print("complete...") deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier) SKPaymentQueue.default().finishTransaction(transaction) } /** Adds to the set of purchases and saves the identifier in UserDefaults Also posts a notification with that transaction so any interested object in the app can listen for it to do things like update the user interface */ private func restore(transaction: SKPaymentTransaction) { guard let productIdentifier = transaction.original?.payment.productIdentifier else { return } print("restore... \(productIdentifier)") deliverPurchaseNotificationFor(identifier: productIdentifier) SKPaymentQueue.default().finishTransaction(transaction) } private func fail(transaction: SKPaymentTransaction) { print("fail...") if let transactionError = transaction.error as NSError?, let localizedDescription = transaction.error?.localizedDescription, transactionError.code != SKError.paymentCancelled.rawValue { print("Transaction Error: \(localizedDescription)") } SKPaymentQueue.default().finishTransaction(transaction) } private func deliverPurchaseNotificationFor(identifier: String?) { guard let identifier = identifier else { return } purchasedProductIdentifiers.insert(identifier) UserDefaults.standard.set(true, forKey: identifier) NotificationCenter.default.post(name: .IAPHelperPurchaseNotification, object: identifier) } }
MasterViewController.swift
import UIKit import StoreKit class MasterViewController: UIViewController { let productIdentifier = String(1196426) var products: [SKProduct] = [] @IBOutlet weak var premiumLabel: UIButton! //Checks if we have the product and moves to the next picture if we do func shouldShowPremium() -> Bool { return Premium.store.isProductPurchased(self.productIdentifier) } override func viewDidLoad() { super.viewDidLoad() title = "RazeFaces" NotificationCenter.default.addObserver(self, selector: #selector(MasterViewController.handlePurchaseNotification(_:)), name: .IAPHelperPurchaseNotification, object: nil) if Premium.store.isProductPurchased(self.productIdentifier) { self.premiumVersion() } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) } @objc func restoreTapped(_ sender: AnyObject) { Premium.store.restorePurchases() } @objc func handlePurchaseNotification(_ notification: Notification) { self.premiumVersion() } func premiumVersion(){ premiumLabel.removeFromSuperview() } @IBAction func buttonPressed(_ sender: UIButton) { sender.titleLabel?.text = "Button pressed" } @IBAction func buyPremium(_ sender: UIButton) { if Premium.store.isProductPurchased(self.productIdentifier){ Premium.store.restorePurchases() }else if IAPHelper.canMakePayments(){ Premium.store.buyProduct(<#T##product: SKProduct##SKProduct#>) }else{ let alert = UIAlertController(title: "Not authorized to make payments", message: "You can not make purchases on this device", preferredStyle: .alert) let ok = UIAlertAction(title: "OK", style: .default, handler: nil) alert.addAction(ok) self.present(alert, animated: true, completion: nil) } } }
Premium.swift
import Foundation
public struct Premium {
public static let store = IAPHelper(productIds: ["1196426"])
}
我完成了本教程,并开始进行应用购买。这个例子就是这个教程比我需要的要复杂得多。我试图创建一个类似的程序,该程序具有两个按钮,位于...
[不要深入研究应用内购买的业务逻辑,首先尝试使用SwiftyStoreKit,基本上SwiftyStoreKit会让您从复杂和不必要的东西中抽象出来