我有一些用户报告说,在尝试应用内购买后,应用现在在启动时崩溃。我已要求他们删除并重新安装未运行的应用程序,并试图要求他们进入飞行模式以停止任何未运行的网络通信。
我无法在我的设备上以任何方式复制错误,我的应用程序内购买在沙盒和生产模式下运行良好。我的想法是,他们的交易以某种方式收到了一个 nil productIdentifier,这导致了启动崩溃,但我不确定在应用程序启动时调用了哪些交易观察器方法,我可以为他们解决这个问题。
是否有某种方法可以“清除”事务队列或以其他方式在启动时测试 nil productidentifiers 并允许这些用户至少再次运行该应用程序?我已经使用下面的代码进行了数百次应用内购买,而这最近才开始发生。应用程序启动时会调用哪些辅助方法?
在 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 的问题,但我无法验证这一点。
StoreKit 会保存一份您的应用程序必须完成的持久事务列表。正如您所注意到的,交易将在每次启动时报告,直到它完成。
我们实现的解决方案是在使用前从入口点检查产品标识符是否为 nil:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
即使我们收到一个产品标识符为零的交易,我们也能够成功调用 finishTransaction
。
希望对您有所帮助。
关于ios - 购买应用程序后,应用程序在启动时崩溃。产品标识符=无?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19817130/