iosswiftskpaymenttransaction

Xcode app issues accessing elements in my ViewController from another class?


In my app, there is a button in the SubscriptionVC that, when pushed, will call the 'purchase' function from the IAPService class. But after the function is completed I wish to change the elements in the ViewController using the ViewController's switchState() method. Does anyone know how to go about this?

class SubscriptionVC: UIViewController{
@IBOutlet weak var slideBtn: UISegmentedControl!
@IBOutlet weak var testLbl: UILabel!

func switchSubscribeState(){
    testLbl.text = “You have changed this label”
    slideBtn.isHidden=true
}

@IBAction func touchSubscribeBtn(_ sender: Any) {
    TestService.shared.buttonPushed( subsriptionVC:self, product: prod)
}

class IAPService: NSObject {
private override init() {}

static let shared = IAPService()
var currentViewController: SubscriptionVC?

func purchase(subsriptionVC: SubscriptionVC ) {
    currentViewController = subsriptionVC
    guard let productToPurchase = products.filter({ $0.productIdentifier == product.rawValue}).first else {return}
    let payment = SKPayment(product: productToPurchase)
    print("payment",product.rawValue)
    paymentQueue.add(payment)
    
}
}
extension IAPService: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
        switch transaction.transactionState {
        case .failed, .deferred:
            SKPaymentQueue.default().finishTransaction(transaction)
            SKPaymentQueue.default().remove(self)
            break
        case .purchasing:
            break
        case .purchased,.restored:
            //Call switchState() when purchased
            subVC?.switchSubscribeState()
            SKPaymentQueue.default().finishTransaction(transaction)
            
            SKPaymentQueue.default().remove(self)
            break
        default:
            SKPaymentQueue.default().finishTransaction(transaction)
            SKPaymentQueue.default().remove(self)
        }
       
    }
}

}

Solution

  • This is a case for the "Delegate Pattern"

    1. Create a Protocol
    protocol IAPServiceDelegate {
      func transactionFinished()
    }
    
    1. Create a property of type IAPServiceDelegate in your IAPService
    var delegate:IAPServiceDelegate?
    
    1. Notify delegate when the transaction is finished.
    case .purchased,.restored:
      SKPaymentQueue.default().finishTransaction(transaction)
      delegate?.transactionFinished()
    
    1. Let your view controller implement that Delegate
    class SubscriptionVC: UIViewController, IAPServiceDelegate {
    
    1. Assign your view controller to as the Delegate to IAPService
    service.delegate = self
    

    (It looks like you use an intermediate class called TestService, so you might have to use that class to implement the delegate or refactor your code)