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

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

问题描述

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

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导致启动崩溃,但我不确定在app启动时调用哪些事务观察器方法我可以为他们解决问题。

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 productidentifier并允许这些用户至少再次运行应用程序?我已经使用下面的代码完成了几百个应用程序购买,而这最近刚开始发生。在app启动时调用哪个辅助方法?

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]];

在应用程序助手代码中:

In app helper code:

- (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.

我希望这会有所帮助。

I hope this helps.

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

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