如何禁用用于应用程序内购买的按钮,而不将其放在另一个线程中?

How to disable a button that serves for an in-App Purchase, without putting it in another thread?

在我的导航栏中,我有一个在应用程序中购买东西的按钮。

let acheterSuppressionPub: UIButton!
let acheterSuppressionPubButtonItem = UIBarButtonItem(customView: acheterSuppressionPub)
acheterSuppressionPub.addTarget(self, action: #selector(ProposerSupprimerPub), for: .touchUpInside)
@objc private func ProposerSupprimerPub() {
        if self.adsView.isHidden == false {
            afficherSupprimerForAllPubAlert()
        }
    }

在视图控制器中,我有这个:

// désactiver les boutons d'achats
        self.acheterSuppressionPub.isEnabled = false
        self.acheterSuppressionPub.isHidden = true
        
        // Purchase
        if(SKPaymentQueue.canMakePayments()) {
            print("IAP is enabled, loading")
            let productID: NSSet = NSSet(objects:
                "com.KingsFit-W.myfood.removeads")
            let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
            request.delegate = self
            request.start()
        } else {
            print("please enable IAPS")
        }

这是建议购买的提醒:

private func afficherSupprimerForAllPubAlert() {
        let alert = UIAlertController(title: NSLocalizedString("Souhaitez-vous enlever définitivement toutes les bannières publicitaires?", comment: ""), message: "\n" + NSLocalizedString("Coût ", comment: "") + NSLocalizedString("xxx€", comment: ""), preferredStyle: .alert)
        
        alert.setValue(attributedString, forKey: "attributedTitle")
        
        alert.addAction(UIAlertAction(title: NSLocalizedString("Enlever la publicité", comment: ""), style: .default, handler: { (action) in
            print("remove ads began")
            for product in self.listeDesAchats {
                let prodID = product.productIdentifier
                if(prodID == "com.xxxxx.xxxxx.removeads") {
                    self.unAchat = product
                    self.buyProduct()
                }
            }
            
        }))
        
        alert.addAction(UIAlertAction(title: NSLocalizedString("Restorer mon achat", comment: ""), style: .default, handler: { (action) in
            
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().restoreCompletedTransactions()
            
        }))
        
        alert.addAction(UIAlertAction(title: NSLocalizedString("Annuler", comment: ""), style: .cancel, handler: { (action) in
            return
        }))
        
        present(alert, animated: true)
    }

购买商品功能如下:

func buyProduct() {
        print("Acheter " + unAchat.productIdentifier)
        let pay = SKPayment(product: unAchat)
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().add(pay as SKPayment)
    }

func removeAds() {
        self.adsView.isHidden = true
        self.acheterSuppressionPub.isHidden = true
        self.acheterSuppressionPub.isEnabled = false
    }

这是问题所在的函数:

func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        print("product request")
        let myProduct = response.products
        for product in myProduct {
            print("product added")
            print(product.productIdentifier)
            print(product.localizedTitle)
            print(product.localizedDescription)
            print(product.price)
            
            listeDesAchats.append(product)
        }
        /////////////////////////////////////////////////////////////////
        self.acheterSuppressionPub.isEnabled = true // it says: -[UIButton setEnabled:] must be used from main thread only
        self.acheterSuppressionPub.isHidden = false
///////////////////////////////////////////////////////
    }

它说:-[UIButton setEnabled:] 只能在主线程中使用

协议函数如下:

func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        print("transactions restored")
        for transaction in queue.transactions {
            let t: SKPaymentTransaction = transaction
            let prodID = t.payment.productIdentifier as String
            
            switch prodID {
                case "com.KingsFit-W.myfood.removeads":
                    print("remove ads")
                    removeAds()
                default:
                    print("IAP not found")
            }
        }
    }

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print("add payment")
        
        for transaction: AnyObject in transactions {
            let trans = transaction as! SKPaymentTransaction
            print(trans.error as Any)
            
            switch trans.transactionState {
            case .purchased:
                print("buy ok, unlock IAP HERE")
                print(unAchat.productIdentifier)
                
                let prodID = unAchat.productIdentifier
                switch prodID {
                    case "xxxxxxxxx.removeads":
                        print("remove ads")
                        removeAds()
                    default:
                        print("IAP not found")
                }
                queue.finishTransaction(trans)
            case .failed:
                print("buy error")
                queue.finishTransaction(trans)
                break
            default:
                print("Default")
                break
            }
        }
    }

我如何禁用和隐藏 acheterSuppressionPub 按钮,而不将它放在另一个线程中? 我想停用它以防止用户在网络请求尚未完成时再次按下它。

所有与接口的通信都必须在主线程上。跳出到主线程与接口对话的标准方式是:

DispatchQueue.main.async {
    self.acheterSuppressionPub.isEnabled = true 
    self.acheterSuppressionPub.isHidden = false
}

同样:

func removeAds() {
    DispatchQueue.main.async {
        self.adsView.isHidden = true
        self.acheterSuppressionPub.isHidden = true
        self.acheterSuppressionPub.isEnabled = false
    }
}