2013-02-14 84 views
1

在我以前的应用中,只有一个IAP,所以我没有意识到我的代码存在问题。今天我有一个应用程序与多个IAP产品,我发现这个问题。iOS,多个IAP(应用内购买)产品,调用付款方式太快

我跟着Troy's IAP tutorial,几乎复制了他的代码。这对我以前的应用程序来说效果很好,因为每个应用程序中只有一个IAP产品。本教程也以一个IAP产品为例。我试图在他的博客上发帖询问我的问题,但是我的帖子太长而且没有格式化,另外我认为这里的专家可以帮助我更多地了解并检查我是否误解了某些内容或错过了某些内容。

现在我必须处理两件事(除非我错过了,本教程没有提到多个IAP产品的情况)。

1,我不知道如果我误解,在本教程中,有一个为loadStore方法的评论,这样

// 
// call this method once on startup 
// 
- (void)loadStore { 
    // restarts any purchases if they were interrupted last time the app was open 
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 

    // get the product description (defined in early sections) 
    [self requestProUpgradeProductData]; 
} 

所以我呼吁我的视图控制器应用程序的开始这种方法。 m文件。我的理解是,这种方法需要检查是否有任何以前的交易挂在那里,并需要在应用程序重新启动时照顾它。这是这个loadStore方法的第一条语句。该方法继续调用requestProUpgradeProductData,它是这样的:在这里

- (void)requestProUpgradeProductData { 
    NSSet *productIdentifiers = [NSSet setWithObject:@"com.runmonster.runmonsterfree.upgradetopro" ]; 
    productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; 
    productsRequest.delegate = self; 
    [productsRequest start]; 

    // we will release the request object in the delegate callback 
} 

注意,在这个方法中的第一条语句是获得IAP产品ID。对于一个IAP产品应用程序来说,这一切都很好,因为产品ID是固定的,并且在运行应用程序开始时调用loadStore是可以的。实际上,loadStore可能必须在运行应用程序的开始时运行,因为这是第二个问题。

2,如果loadStore运行在用户想要购买IAP,而不是在应用程序开始时的那一刻,美中不足的是,当[productRequest开始]运行,下面的方法将运行:

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response 
{ 
    NSArray *products = response.products; 
    proUpgradeProduct = [products count] == 1 ? [[products firstObject] retain] : nil; 
    if (proUpgradeProduct) 
    { 
    NSLog(@"Product title: %@" , proUpgradeProduct.localizedTitle); 
    NSLog(@"Product description: %@" , proUpgradeProduct.localizedDescription); 
    NSLog(@"Product price: %@" , proUpgradeProduct.price); 
    NSLog(@"Product id: %@" , proUpgradeProduct.productIdentifier); 
    } 

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

    // finally release the reqest we alloc/init’ed in requestProUpgradeProductData 
    [productsRequest release]; //I didn't do this because of ARC 

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

这将运行并返回产品的响应。那么我需要开始支付,但我不确定HRER如何按照方法进行调用。这是启动IAP付款的方法。正如我所提到的,一旦loadStore运行在应用程序的开始处,有充足的时间用于productRequest ....响应方法(正上方)完成并发回通知,因为用户在这里和那里点击一秒钟。正如我所说的,对于一个IAP产品应用程序,这很好,我可以在开始时指定产品ID。现在对于具有多个IAP产品的应用程序,我需要向用户展示多个产品,并且用户从中选择其中一个。在此之后,我需要两件事情:A,通过loadStore - > productRequest方法(正上方)和B指定哪个IAP产品调用以下方法启动付款。

- (void)purchaseProUpgrade 
{ 
    SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId]; 
    [[SKPaymentQueue defaultQueue] addPayment:payment]; 
} 

但是,在我呼叫支付启动方法的那一刻,productRequest .....响应方法可能还没有返回。我将无法启动付款。我正在考虑在一秒钟左右之间放置一个延迟函数,但我认为这种方法从根本上是错误的。但是,如何解决这个问题呢?

任何人都可以帮忙吗?

回答

1

关键是你不能让用户购买任何东西,直到你从productsRequest得到回应。首先,initWithProductIdentifiers:需要一组标识符。因此,在向用户展示购买选项之前,在应用启动或任何其他时间,您可以为所有可能允许用户购买的产品使用标识符/ skus进行调用。在启动时调用它对我来说似乎很浪费,但它也应该可以工作,并且可能是某些应用程序的唯一选项。

只有在获得包含产品对象的productsRequest:didReceiveResponse:回调后,您是否允许用户单击/触摸或以其他方式调用该产品的购买操作。您必须在允许用户尝试购买之前检查回复以确保产品存在。我有一个购买屏幕,当用户输入它时,我会调用productsRequest,其中包含与应用程序当前状态相关的所有产品(例如,省略已购买的商品或按级别限制产品)。我也创建了购买屏幕,但我没有用任何产品来填充它。在响应委托中,我实际上在屏幕上填充了可购买的对象。这样,用户就不能尝试购买无效的产品。

当用户点击/水龙头,您使用的产品对象从响应创建使用支付对象:

[SKPayment paymentWithProduct:product] 

注意,这是从使用paymentWithProductIdentifier:当前设置的变化 - 一个方法已过时。

+0

不错。听起来对我来说合理。我会尝试你的策略并回到你的答案。谢谢。 – 2013-02-15 06:48:32

+0

按照您的解释重新安排了我的代码逻辑,现在它可以工作。接受你的答案。 – 2013-02-15 21:42:50

相关问题