IPhone - SKProductsRequest and "message sent to an exempted instance"

I'm having trouble implementing InAppPurchase. My purchase implementation is in the modal view controller (AppUpgradeViewController), which I present from another modal view. I do it like this:

AppUpgradeViewController * appUpgradeViewController = [[AppUpgradeViewController alloc] init];
appUpgradeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
appUpgradeViewController.delegate = self;
[self presentModalViewController:appUpgradeViewController animated:YES];
[appUpgradeViewController release];

Then in my update view, I do the following:

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSSet *productIdentifiers = [NSSet setWithObject:kInAppPurchaseProUpgradeProductId];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self;
[productsRequest start];

Then i implemented

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

where am i doing:

[self.productsRequest release];

and then I have other necessary methods.

The problem is when I show the modal and quickly turn it off, and then after a few seconds I got the following on the console (I turned on NSZombieEnabled):

*** -[AppUpgradeViewController respondsToSelector:]: message sent to deallocated instance 0x2e91f0

, - , , . , ( ), , /dealloc. !

+5
5

. , . , SKProductsRequest, message sent to deallocated instance. , cancel (. reference) SKProductsRequest.

nil.

:

NSSet *productIdentifiers = [NSSet setWithObject:@"MY_IDENTIFIER"];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];

, dealloc, .

productsRequest.delegate = nil;
[productsRequest cancel];
productsRequest = nil;

SKPaymentQueue, .

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
+9

, , AppUpgradeViewController dealloc:

- (void)dealloc {
   ...
   productsRequest.delegate = nil;
   [productsRequest release], productsRequest = nil;
   ...
   [super dealloc];
}
+4

, , productRequest, , , nil, , .

productsRequest? retain, :

[self.productsRequest release];

:

self.productsRequest = nil; // Property will do the release for you.

assign, :

[self.productsRequest release];
self.productsRequest = nil; // Or else some might access this pointer,
                            // which now might point to nirvana.
+2
source

This is because you are doing this:

[appUpgradeViewController release]; 

too early?

Try this in the dealloc method of any class into which you distribute it. Of course, you do not select it more than once. It will also require you to move the declaration to the class header.

0
source

Swift 3

It is a good idea to close the request if you run it. This is a safe way to do this in Swift.

    // strong reference at top of class
    var productRequest: SKProductsRequest!

    // at some point you will fetch products

    // on deallocating the window
    if productRequest != nil {
        productRequest.cancel()
        productRequest.delegate = nil
    }
0
source

All Articles