Reputation: 417
Running a test for my in app purchase (first time doing in app purchases). I get EXC_BAD_ACCESS on the third line of this code:
SKPayment *payment = [SKPayment paymentWithProduct:electronicProd];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
The is under an IBAction for a button. electronicPack is declared in the header as a SKProduct. Threw some NSLogs in the productsRequest didReceiveResponse, and when the product was requested (in the viewDidLoad) and they showed it was correctly fetching the product and storing it in electronicPack. Defined electronicPack as [[request.products] objectAtIndex:0] in the didReceiveResponse page. So yea. Thats where im at, dont know what to do. Any help is appreciated.
UPDATE: FIXED accidentally left in code that was adding an extra transaction observer lol
Upvotes: 23
Views: 5732
Reputation: 3603
If you're creating a dedicated class for SKPaymentTransactionObserver
don't forget that it must be retained.
I got the error before realizing this, here's an example in AppDelegate
:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var myTransactionObserver: MyTransactionObserver!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// don't
let myTransactionObserver = MyTransactionObserver()
// do
myTransactionObserver = MyTransactionObserver()
SKPaymentQueue.default().add(myTransactionObserver)
return true
}
// ...
}
Upvotes: 1
Reputation: 3081
I Have the same issue, my solution was to call [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
on store observer transaction finish/failed/completed callbacks
Upvotes: 0
Reputation: 5656
Mr.T answer is the best solution!
In swift I call this removeTransactionObserver here:
deinit {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
Upvotes: 12
Reputation: 808
I had the same error, quite simple to solve really. In my header file I had a SKProduct declared:
@property SKProduct *product;
I just changed it to:
@property (retain) SKProduct *product;
and it all works fine. Hope this helps someone.
Upvotes: 2
Reputation: 24902
Seems like the issue is from trying to add a transaction observer before removing the previous one. Add the following to your controller to fix this issue:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
Hope this helps!
Upvotes: 27
Reputation: 754
I've had the same issue, my solution was to call
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
on leaving the In-App Store in my App. Maybe it will help someone in the future.
Upvotes: 41
Reputation: 4286
You need to retain the object that you are creating
- (void)viewDidLoad {
//... stuff
SKProduct* electronicProduct = //...
[electronicProduct retain];
//... otherstuff
}
viewDidLoad is wrapped by the system in a autorelease pool, paymentWithProduct: returns an autorelease object. When viewDidLoad is done, all autorelease object are released, that's why you get a bad memory access when you try to access to it later.
Upvotes: 10