2013-02-14 87 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

相關問題