In app purchase with Automatic Reference Couting:

2019-09-06 18:32发布

I've now been trying for two days to implement in app purchase in an iOS app, with the same error bugging me.

I get an EXC_BAC_ACCESS error every time I try to start my SKProductsRequest object.

I've read dozens of people having me same error, but none of the solutions seems to work for me.

When I set NSZombieEnabled, i get following error:

[AppShopper respondsToSelector:]: message sent to deallocated instance 0x1d9340

Here's my AppShopper.h:

#import <StoreKit/StoreKit.h>

#define kInAppPurchaseManagerProductsFetchedNotification @"kInAppPurchaseManagerProductsFetchedNotification"


@interface AppShopper : NSObject <SKProductsRequestDelegate>

@property (nonatomic, strong) SKProduct *product;
@property (nonatomic, strong) SKProductsRequest *request;

- (void) requestProductData;

@end

And my AppShopper.m:

#import "AppShopper.h"

@implementation AppShopper

#define productId @"XXX.ProductID.XXX"

@synthesize request = _request;
@synthesize product = _product;

- (void) request:(SKRequest *)request didFailWithError:(NSError *)error{
    printf("Error!\n");
    _request = nil;
    _product = nil;
}

- (void) requestDidFinish:(SKRequest *)request {
    printf("Finished request!\n");
}

- (void) requestProductData{
    printf("requestProductData\n");

    NSSet *productIdentifiers = [NSSet setWithObject:productId];

    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers: productIdentifiers];

    self.request.delegate = self;
    [self.request start];

    printf("requestProductData End\n");
}

#pragma mark -
#pragma mark SKProductsRequestDelegate methods

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    printf("productsRequest\n");
    NSArray *products = response.products;

    self.product = [products count] == 1 ? [products objectAtIndex:0] : nil;
    if (self.product)
    {
        NSLog(@"Product title: %@" , self.product.localizedTitle);
        NSLog(@"Product description: %@" , self.product.localizedDescription);
        NSLog(@"Product price: %@" , self.product.price);
        NSLog(@"Product id: %@" , self.product.productIdentifier);
    }

    for (NSString *invalidProductId in response.invalidProductIdentifiers)
    {
        NSLog(@"Invalid product id: %@" , invalidProductId);
    }

    _request = nil;
    _product = nil;

    [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
}


@end

I try to start the in app purchase with the following code:

AppShopper *shopper = [[AppShopper alloc] init];
[shopper requestProductData];

My output is only:

requestProductData
requestProductData End

2012-09-10 19:43:30.210 MyApp[4327:707] *** -[AppShopper respondsToSelector:]: message sent to deallocated instance 0x1d9340

And, yes I am:

  1. testing on a physical device
  2. in sandbox environment with test user
  3. with a proper provisioning profile

Any help appreciated, thanks.

2条回答
家丑人穷心不美
2楼-- · 2019-09-06 18:34

The bug will be in whichever object makes your AppShopper.

For example,

AppShopper *shopper = [AppShopper new];
... setup shopper here ...
[shopper requestProductData];

How does ARC know that you want to keep your AppShopper around? It doesn't and it will release it immediately after requestProductData. Then, when the request returns it will try to call it's delegate methods, which won't exist anymore.

Try storing your AppShopper as a strong property instead of a local variable and see if that helps.

查看更多
戒情不戒烟
3楼-- · 2019-09-06 19:00

First of all, add these functions in

In AppShopper.m

//Checks if the device or user can make purchases
- (BOOL)canMakePurchases
{
    return [SKPaymentQueue canMakePayments];
}

File from which you call, initiate the inApp purchase in this way

AppShopper *shopper = [[AppShopper new];
if([shopper canMakePurchases])
{
    [shopper requestProductData];
}
查看更多
登录 后发表回答