在应用程序购买之后,应用程序在启动时崩溃.productIdentifier=nil? [英] Following in app purchase, app crashing on startup. productIdentifier=nil?

查看:16
本文介绍了在应用程序购买之后,应用程序在启动时崩溃.productIdentifier=nil?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些用户报告说,在尝试进行应用内购买后,应用现在在启动时崩溃.我已要求他们删除并重新安装无效的应用程序,并试图要求他们进入飞行模式以停止任何无效的网络通信.

I have a few users who have reported that after attempting an in app purchase the app is now crashing on startup. I have asked them to delete and reinstall the app which has not worked, and attempted to ask them to go into airplane mode to stop any network communication that has not worked.

我无法在我的设备上以任何方式复制错误,而且我的应用内购买在沙盒和生产模式下都很好.我的想法是,他们的交易以某种方式收到了一个 nil productIdentifier,这导致了启动崩溃,但我不确定在应用启动时调用了哪些交易观察者方法,我可以为他们解决问题.

I am unable to replicate the error in anyway on my devices and my in app purchase goes through just fine in sandbox and production modes. My thought is that somehow their transaction received a nil productIdentifier which is causing the startup crash but I am not sure what transaction observer methods get called at app startup that I can fix the issue for them.

有没有办法在启动时清除"事务队列或以其他方式测试 nil productidentifiers 并允许这些用户至少再次运行应用程序?我已经使用下面的代码完成了数百次应用内购买,而这只是最近才开始发生的.在应用程序启动时调用了哪些辅助方法?

Is there someway to "clear" the transaction queue or otherwise test for nil productidentifiers on start up and allow these users to get the app at least running again? I've done several hundred in app purchases using the code below and this just recently began happening. Which of the helper methods get called on app startup?

在 AppDelegate.m 中

In AppDelegate.m

[[SKPaymentQueue defaultQueue] addTransactionObserver:[MovieClockIAPHelper sharedHelper]];

应用内帮助程序代码:

- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {
    if ((self = [super init])) {

        // Store product identifiers
        _productIdentifiers = [productIdentifiers retain];

        // Check for previously purchased products

        NSMutableSet * purchasedProducts = [NSMutableSet set];
        for (NSString * productIdentifier in _productIdentifiers) {

            BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];

            if (productPurchased) {
                [purchasedProducts addObject:productIdentifier];
                NSLog(@"Previously purchased: %@", productIdentifier);
            }
            else{
            NSLog(@"Not purchased: %@", productIdentifier);
            }
        }
        self.purchasedProducts = purchasedProducts;

    }
    return self;
}

- (void)requestProducts {

    self.request = [[[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers] autorelease];
    _request.delegate = self;
    [_request start];

}

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

    NSLog(@"Received products results...");   
    self.products = response.products;
    self.request = nil;    

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:_products];    
}


- (void)restoreCompletedTransactions {
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

- (void)provideContent:(NSString *)productIdentifier {

    NSLog(@"Toggling flag for: %@", productIdentifier);
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [_purchasedProducts addObject:productIdentifier];

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];

}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"completeTransaction...");

    [self recordTransaction: transaction];
    [self provideContent: transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"restoreTransaction...");


    [self recordTransaction: transaction];
    [self provideContent: transaction.originalTransaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {

    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    NSLog(@"in the payment queue");

    for (SKPaymentTransaction *transaction in transactions)
    {

        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
            default:
                break;
        }
        }

}

-(void)buyProduct:(SKProduct *)product
{
    NSLog(@"In buyproduct Buying %@...", product.productIdentifier);

    SKPayment *payment = [SKPayment paymentWithProduct:product];

    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)dealloc
{
    [_productIdentifiers release];
    _productIdentifiers = nil;
    [_products release];
    _products = nil;
    [_purchasedProducts release];
    _purchasedProducts = nil;
    [_request release];
    _request = nil;
    [super dealloc];
}

@end

推荐答案

当事务处于 SKPaymentTransactionStateRestored 时,我遇到了类似的问题.我的测试表明这可能是 IOS 7.0.3 的问题,但我无法验证这一点.

I've run into a similar issue when the transaction is in the SKPaymentTransactionStateRestored. My testing has indicated this might be an issue with IOS 7.0.3, but I have not been able to verify this.

StoreKit 会保存您的应用程序必须完成的事务的持久列表.正如您所指出的,事务将在每次启动时报告,直到完成.

StoreKit keeps a persistent list of transactions that your application must finish. As you've noted the transaction will be reported on every startup until it is finished.

我们实施的解决方案是在使用前从入口点检查产品标识符是否为零:

The solution that we implemented is to check if the product identifier is nil before usage from the entry point:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

即使我们收到产品标识符为零的交易,我们也能够成功调用 finishTransaction.

Even when we received a transaction with a nil product identifier we were able to successfully call finishTransaction.

我希望这会有所帮助.

这篇关于在应用程序购买之后,应用程序在启动时崩溃.productIdentifier=nil?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆