0

I'm using this IAP implementation guide and when a purchase is final, it posts a notification using this code:

NotificationCenter.default.post(name: NSNotification.Name(rawValue: IAPHelper.IAPHelperPurchaseNotification), object: identifier)

The implementation doesn't include observer code, so I added the below into the function that runs when the "Buy" button is pressed:

var functionToRun = #selector(MyViewController.runAfterBoughtFunc)
NotificationCenter.default.addObserver(self, selector: functionToRun, name: NSNotification.Name(rawValue: IAPHelper.IAPHelperPurchaseNotification), object:nil)

My problem is that when the NotificationCenter.default.post(...) code gets called I get this error:

...runAfterBoughtFuncWithNotif:]: unrecognized selector sent to instance 0x100f12fc0
(lldb) 

Notes

  1. If I comment-out the observer code, I no longer get an error.
  2. If you look at the IAP Guide I'm using, in the comments another user had the same problem, so this is not isolated to only my code

Anyone know how to fix it?

Dave G
  • 12,042
  • 7
  • 57
  • 83

1 Answers1

0

Because no answers were posted, I had to come up with a work around. So if you're having trouble with using the observer pattern, you can try this alternative.

My Custom Observer

The below code has a variable to hold the status of the thing being observed. It then uses a timer to periodically run a function that checks that variable to see if the state changed. The below example is of observing a purchase status.

  1. Set a variable that points at our custom observer, mine is checkPurchase status. You'll most likely want to add this to the button-push code or viewDidLoad, whatever sets things off.

    let selector = #selector(myViewController.checkPurchaseStatus)
    
  2. Then set a timer that periodically runs that runs the function, in my case it will run "checkPurchaseStatus" once each second. Add this under the above code.

    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: selector, userInfo: nil, repeats: true)
    
  3. Then set a variable that keeps track of the "state". If the state will be determined by another ViewController, you can make this a global variable:

    var purchaseState = ""
    
  4. List item

    func checkPurchaseStatus () {
        switch purchaseState {
        case "":
            print("Waiting for purchase...")
        case "failed":
            timer.invalidate() //turns timer off
            purchaseState = "" //resets the variable for future uses
            //Add more code to be run if the purchase failed
            print("Purchased failed. Timer stopped.")
        case "succeeded":
            timer.invalidate() //turns timer off
            purchaseState = "" //resets the variable for future uses
            //Add more code to be run if the purchase succeeded
            print("Purchased succeeded. Timer stopped.")
        default:
            break
        }
    }
    

And that's it! It's not as powerful as an observer but it's a simple, quick way to get the job done in most situations!

Dave G
  • 12,042
  • 7
  • 57
  • 83