In my navigation bar i have a button to buy something in the app.
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()
}
}
In the view controller, i have this:
// 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")
}
Here is the alert to propose the purchase:
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)
}
Here is the functions to buy the product:
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
}
Here is the function where the problem is:
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
///////////////////////////////////////////////////////
}
it says: -[UIButton setEnabled:] must be used from main thread only
Here are the protocol functions:
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
}
}
}
How could i disable and hidden the acheterSuppressionPub button, without putting it in a another thread? I want to deactivate it to prevent the user from pressing it again when the network request has not yet finished.
All communication with the interface must be on the main thread. The standard way to step out to the main thread to talk to the interface is:
DispatchQueue.main.async {
self.acheterSuppressionPub.isEnabled = true
self.acheterSuppressionPub.isHidden = false
}
Similarly:
func removeAds() {
DispatchQueue.main.async {
self.adsView.isHidden = true
self.acheterSuppressionPub.isHidden = true
self.acheterSuppressionPub.isEnabled = false
}
}