StoreKit:从Swift 1.2转换为Swift 3时出错

时间:2017-07-14 02:08:19

标签: ios swift storekit

我有一个示例项目,了解如何使用Apple的StoreKit,这样我就可以学习将自动更新订阅服务应用到我的应用程序和任何应用程序服务中。

问题是示例项目是在Swift 1.2中进行的,并且在将其转换为Swift 3时,我遇到了几个错误,但我遇到了2个警告和2个错误。希望有人可以帮助我。

此外,在将代码转换为Swift 3时,代码仍然有效吗?既然它老了?应用内购买是否有任何重大改变?

包含警告和错误的代码

func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {

    var products = response.products

    if (products.count != 0) {
        for i in 0 ..< products.count
        {
            self.product = products[i] as? SKProduct
            self.productsArray.append(product!)
        }
        self.tableView.reloadData()
    } else {
        print("No products found")
    }

    products = response.invalidProductIdentifiers

    for product in products
    {
        print("Product not found: \(product)")
    }
}

func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
    print("Transactions Restored")

    var purchasedItemIDS = []
    for transaction:SKPaymentTransaction in queue.transactions {

        if transaction.payment.productIdentifier == "com.brianjcoleman.testiap1"
        {
            print("Consumable Product Purchased")
            // Unlock Feature
        }
        else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap2"
        {
            print("Non-Consumable Product Purchased")
            // Unlock Feature
        }
        else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap3"
        {
            print("Auto-Renewable Subscription Product Purchased")
            // Unlock Feature
        }
        else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap4"
        {
            print("Free Subscription Product Purchased")
            // Unlock Feature
        }
        else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap5"
        {
            print("Non-Renewing Subscription Product Purchased")
            // Unlock Feature
        }
    }

    let alert = UIAlertView(title: "Thank You", message: "Your purchase(s) were restored.", delegate: nil, cancelButtonTitle: "OK")
    alert.show()
}

second error

first error

Store Kit的其余代码

var tableView = UITableView()
let productIdentifiers = Set(["com.brianjcoleman.testiap1", "com.brianjcoleman.testiap2", "com.brianjcoleman.testiap3", "com.brianjcoleman.testiap4", "com.brianjcoleman.testiap5"])
var product: SKProduct?
var productsArray = Array<SKProduct>()

func requestProductData()
{
    if SKPaymentQueue.canMakePayments() {
        let request = SKProductsRequest(productIdentifiers:
            self.productIdentifiers as Set<String>)
        request.delegate = self
        request.start()
    } else {
        let alert = UIAlertController(title: "In-App Purchases Not Enabled", message: "Please enable In App Purchase in Settings", preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "Settings", style: UIAlertActionStyle.default, handler: { alertAction in
            alert.dismiss(animated: true, completion: nil)

            let url: URL? = URL(string: UIApplicationOpenSettingsURLString)
            if url != nil
            {
                UIApplication.shared.openURL(url!)
            }

        }))
        alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: { alertAction in
            alert.dismiss(animated: true, completion: nil)
        }))
        self.present(alert, animated: true, completion: nil)
    }
}

func buyProduct(_ sender: UIButton) {
    let payment = SKPayment(product: productsArray[sender.tag])
    SKPaymentQueue.default().add(payment)
}

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {

    for transaction in transactions {

        switch transaction.transactionState {

        case SKPaymentTransactionState.purchased:
            print("Transaction Approved")
            print("Product Identifier: \(transaction.payment.productIdentifier)")
            self.deliverProduct(transaction)
            SKPaymentQueue.default().finishTransaction(transaction)

        case SKPaymentTransactionState.failed:
            print("Transaction Failed")
            SKPaymentQueue.default().finishTransaction(transaction)
        default:
            break
        }
    }
}

func deliverProduct(_ transaction:SKPaymentTransaction) {

    if transaction.payment.productIdentifier == "com.brianjcoleman.testiap1"
    {
        print("Consumable Product Purchased")
        // Unlock Feature
    }
    else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap2"
    {
        print("Non-Consumable Product Purchased")
        // Unlock Feature
    }
    else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap3"
    {
        print("Auto-Renewable Subscription Product Purchased")
        // Unlock Feature
    }
    else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap4"
    {
        print("Free Subscription Product Purchased")
        // Unlock Feature
    }
    else if transaction.payment.productIdentifier == "com.brianjcoleman.testiap5"
    {
        print("Non-Renewing Subscription Product Purchased")
        // Unlock Feature
    }
}

func restorePurchases(_ sender: UIButton) {
    SKPaymentQueue.default().add(self)
    SKPaymentQueue.default().restoreCompletedTransactions()
}

的TableView

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cellFrame = CGRect(x: 0, y: 0, width: self.tableView.frame.width, height: 52.0)
    let retCell = UITableViewCell(frame: cellFrame)

    if self.productsArray.count != 0
    {
        if indexPath.row == 5
        {
            let restoreButton = UIButton(frame: CGRect(x: 10.0, y: 10.0, width: UIScreen.main.bounds.width - 20.0, height: 44.0))
            restoreButton.titleLabel!.font = UIFont (name: "HelveticaNeue-Bold", size: 20)
            restoreButton.addTarget(self, action: #selector(ViewController.restorePurchases(_:)), for: UIControlEvents.touchUpInside)
            restoreButton.backgroundColor = UIColor.black
            restoreButton.setTitle("Restore Purchases", for: UIControlState())
            retCell.addSubview(restoreButton)
        }
        else
        {
            let singleProduct = productsArray[indexPath.row]

            let titleLabel = UILabel(frame: CGRect(x: 10.0, y: 0.0, width: UIScreen.main.bounds.width - 20.0, height: 25.0))
            titleLabel.textColor = UIColor.black
            titleLabel.text = singleProduct.localizedTitle
            titleLabel.font = UIFont (name: "HelveticaNeue", size: 20)
            retCell.addSubview(titleLabel)

            let descriptionLabel = UILabel(frame: CGRect(x: 10.0, y: 10.0, width: UIScreen.main.bounds.width - 70.0, height: 40.0))
            descriptionLabel.textColor = UIColor.black
            descriptionLabel.text = singleProduct.localizedDescription
            descriptionLabel.font = UIFont (name: "HelveticaNeue", size: 12)
            retCell.addSubview(descriptionLabel)

            let buyButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.width - 60.0, y: 5.0, width: 50.0, height: 20.0))
            buyButton.titleLabel!.font = UIFont (name: "HelveticaNeue", size: 12)
            buyButton.tag = indexPath.row
            buyButton.addTarget(self, action: #selector(ViewController.buyProduct(_:)), for: UIControlEvents.touchUpInside)
            buyButton.backgroundColor = UIColor.black
            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = Locale.current
            buyButton.setTitle(numberFormatter.string(from: singleProduct.price), for: UIControlState())
            retCell.addSubview(buyButton)
        }
    }

    return retCell
}

1 个答案:

答案 0 :(得分:2)

第一个函数中的两个问题都来自于before Swift 3,NSArrays的导入没有它们的泛型类型(即[SKProduct],而不是as? SKProduct)。

简单地删除// Old for i in 0 ..< products.count { self.product = products[i] as? SKProduct self.productsArray.append(product!) } // New: productsArray.append(contentsOf: products) 部分会修复警告,但在一次调用中添加所有内容会更清晰:

response.products

错误是因为虽然response.invalidProductIdentifiers[Any]最初都是[SKProduct]导入,但现在它们已被输入([String]// Old: products = response.invalidProductIdentifiers for product in products // New: for product in response.invalidProductIdentifiers )。最简单的解决方案就是直接使用数组:

[String]

由于它只是打印,我可能只是直接打印数组。

第二个函数中的错误是因为编译器需要知道变量应该是什么类型的数组。从名称来看,我猜它本来是class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, SKProductsRequestDelegate, SKPaymentTransactionObserver { enum Product: String { case test1 = "com.brianjcoleman.testiap1" case test2 = "com.brianjcoleman.testiap2" case test3 = "com.brianjcoleman.testiap3" case test4 = "com.brianjcoleman.testiap4" case test5 = "com.brianjcoleman.testiap5" static var allValues: [Product] { return [.test1, .test2, .test3, .test4, .test5] } } let tableView = UITableView() var productsArray = [SKProduct]() override func viewDidLoad() { super.viewDidLoad() tableView.frame = self.view.frame tableView.separatorColor = .clear tableView.dataSource = self tableView.delegate = self self.view.addSubview(tableView) SKPaymentQueue.default().add(self) self.requestProductData() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) SKPaymentQueue.default().remove(self) } // In-App Purchase Methods func requestProductData() { if SKPaymentQueue.canMakePayments() { let productIdentifiers = Set(Product.allValues.map { $0.rawValue }) let request = SKProductsRequest(productIdentifiers: productIdentifiers) request.delegate = self request.start() } else { let alert = UIAlertController(title: "In-App Purchases Not Enabled", message: "Please enable In App Purchase in Settings", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Settings", style: .default, handler: { _ in alert.dismiss(animated: true, completion: nil) if let url = URL(string: UIApplicationOpenSettingsURLString) { UIApplication.shared.openURL(url) } })) alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { _ in alert.dismiss(animated: true, completion: nil) })) self.present(alert, animated: true, completion: nil) } } func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { let products = response.products if products.count != 0 { productsArray.append(contentsOf: products) self.tableView.reloadData() } else { print("No products found") } let invalidIdentifiers = response.invalidProductIdentifiers if invalidIdentifiers.count > 0 { print("Invalid product identifiers: \(invalidIdentifiers)") } } func buyProduct(_ sender: UIButton) { let payment = SKPayment(product: productsArray[sender.tag]) SKPaymentQueue.default().add(payment) } func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchased, .restored: print("Transaction Approved") print("Product Identifier: \(transaction.payment.productIdentifier)") self.deliverProduct(transaction) SKPaymentQueue.default().finishTransaction(transaction) case .failed: print("Transaction Failed") SKPaymentQueue.default().finishTransaction(transaction) case .deferred, .purchasing: break } } } func deliverProduct(_ transaction:SKPaymentTransaction) { } func restorePurchases(_ sender: UIButton) { SKPaymentQueue.default().add(self) SKPaymentQueue.default().restoreCompletedTransactions() } func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { print("Transactions Restored") for transaction in queue.transactions { processTransaction(transaction: transaction) } let alert = UIAlertController(title: "Thank You", message: "Your purchase(s) were restored.", preferredStyle: .alert) present(alert, animated: true) } private func processTransaction(transaction: SKPaymentTransaction) { guard let product = Product(rawValue: transaction.payment.productIdentifier) else { print("Unknown product identifier: \(transaction.payment.productIdentifier)") return } switch product { case .test1: print("Consumable Product Purchased") // Unlock Feature case .test2: print("Non-Consumable Product Purchased") // Unlock Feature case .test3: print("Auto-Renewable Subscription Product Purchased") // Unlock Feature case .test4: print("Free Subscription Product Purchased") // Unlock Feature case .test5: print("Non-Renewing Subscription Product Purchased") // Unlock Feature } } // Screen Layout Methods func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.productsArray.count + 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellFrame = CGRect(x: 0, y: 0, width: self.tableView.frame.width, height: 52.0) let retCell = UITableViewCell(frame: cellFrame) if self.productsArray.count != 0 { if indexPath.row == Product.allValues.count { let restoreButton = UIButton(frame: CGRect(x: 10.0, y: 10.0, width: UIScreen.main.bounds.width - 20.0, height: 44.0)) restoreButton.titleLabel?.font = UIFont(name: "HelveticaNeue-Bold", size: 20) restoreButton.addTarget(self, action: #selector(ViewController.restorePurchases(_:)), for: .touchUpInside) restoreButton.backgroundColor = .black restoreButton.setTitle("Restore Purchases", for: .normal) retCell.addSubview(restoreButton) } else { let singleProduct = productsArray[indexPath.row] let titleLabel = UILabel(frame: CGRect(x: 10.0, y: 0.0, width: UIScreen.main.bounds.width - 20.0, height: 25.0)) titleLabel.textColor = .black titleLabel.text = singleProduct.localizedTitle titleLabel.font = UIFont(name: "HelveticaNeue", size: 20) retCell.addSubview(titleLabel) let descriptionLabel = UILabel(frame: CGRect(x: 10.0, y: 10.0, width: UIScreen.main.bounds.width - 70.0, height: 40.0)) descriptionLabel.textColor = .black descriptionLabel.text = singleProduct.localizedDescription descriptionLabel.font = UIFont(name: "HelveticaNeue", size: 12) retCell.addSubview(descriptionLabel) let buyButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.width - 60.0, y: 5.0, width: 50.0, height: 20.0)) buyButton.titleLabel?.font = UIFont(name: "HelveticaNeue", size: 12) buyButton.tag = indexPath.row buyButton.addTarget(self, action: #selector(ViewController.buyProduct(_:)), for: .touchUpInside) buyButton.backgroundColor = .black let numberFormatter = NumberFormatter() numberFormatter.numberStyle = .currency numberFormatter.locale = .current buyButton.setTitle(numberFormatter.string(from: singleProduct.price), for: .normal) retCell.addSubview(buyButton) } } return retCell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 52.0 } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { if section == 0 { return 64.0 } return 32.0 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let ret = UILabel(frame: CGRect(x: 10, y: 0, width: self.tableView.frame.width - 20, height: 32.0)) ret.backgroundColor = .clear ret.text = "In-App Purchases" ret.textAlignment = .center return ret } } ,但它没有被使用(因为同一行上的警告表示),所以你也可以删除该行。

完整的更新/现代化/统一风格的视图控制器:

{{1}}