2013-05-16 30 views
0

因此,我一直试图在我的应用程序中设置应用程序购买,并遇到了一个我不知道如何解决的问题。我正在与Xamarin合作,并且我遵循他们的In app purchase guide关于如何购买耗材产品。在应用程序中购买xamarin中的内存泄漏

一切都很顺利,直到我试图让苹果返回的交易收据。每次我从SKPaymentTransaction对象(在我的项目中的任何地方)访问这个属性时,我得到这个错误,根据一些人的说法是内存泄漏。只要我访问这个属性(SKPaymentTransaction.TransactionReceipt),就会发生这种情况。

错误:

*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 

我的代码看起来很像一个在我以前告诉你的指导找到。首先,我创建了一个在应用程序内购买管理器,它是一个负责,以获得产品信息(这伟大工程),并更新我的UI发出请求苹果只要一个交易成功还是失败:

public class InAppPurchaseManager : SKProductsRequestDelegate 
{ 
    IMobileServiceTable receiptTable = AppDelegate.MobileService.GetTable("Receipt"); 

    public InAppPurchaseManager() 
    { 
     SKPaymentQueue.DefaultQueue.AddTransactionObserver (new TransactionObserver(this)); 
    } 

    public void RequestProductData (List<NSString> productIds) 
    { 
     var array = new NSString[productIds.Count]; 
     for (var i = 0; i < productIds.Count; i++) { 
      array[i] = productIds[i]; 
     } 
     NSSet productIdentifiers = NSSet.MakeNSObjectSet<NSString>(array); 
     var productsRequest = new SKProductsRequest(productIdentifiers); 
     productsRequest.Delegate = this; // for SKProductsRequestDelegate.ReceivedResponse 
     productsRequest.Start(); 
    } 

    public override void ReceivedResponse (SKProductsRequest request, SKProductsResponse response) 
    { 
     SKProduct[] products = response.Products; 
     NSDictionary userInfo = null; 
     if (products.Length > 0) { 
      NSObject[] productIdsArray = new NSObject[response.Products.Length]; 
      NSObject[] productsArray = new NSObject[response.Products.Length]; 
      for (int i = 0; i < response.Products.Length; i++) { 
       productIdsArray[i] = new NSString(response.Products[i].ProductIdentifier); 
       productsArray[i] = response.Products[i]; 
      } 
      userInfo = NSDictionary.FromObjectsAndKeys (productsArray, productIdsArray); 
     } 
     NSNotificationCenter.DefaultCenter.PostNotificationName ("InAppPurchaseManagerProductsFetchedNotification", this, userInfo); 
    } 

    public override void RequestFailed (SKRequest request, NSError error) 
    { 
     Console.WriteLine (" ** InAppPurchaseManager RequestFailed() " + error.LocalizedDescription); 
    } 

    public void PuchaseProduct (SKProduct product) 
    { 
      SKPayment payment = SKPayment.PaymentWithProduct (product); 
      SKPaymentQueue.DefaultQueue.AddPayment (payment); 
    } 

    public void CompleteTransaction (SKPaymentTransaction transaction) 
    { 
     var productId = transaction.Payment.ProductIdentifier; 
     // Register the purchase, so it is remembered for next time 
     FinishTransaction(transaction, true); 
    } 

    public void FinishTransaction(SKPaymentTransaction transaction, bool wasSuccessful) 
    { 
     // remove the transaction from the payment queue. 
     SKPaymentQueue.DefaultQueue.FinishTransaction(transaction); 
     using (var pool = new NSAutoreleasePool()) { 
      NSDictionary userInfo = NSDictionary.FromObjectsAndKeys(new NSObject[] {transaction},new NSObject[] {new NSString("transaction")}); 
      if (wasSuccessful) {     NSNotificationCenter.DefaultCenter.PostNotificationName (new NSString("InAppPurchaseManagerTransactionSuccedeedNotification"), this, userInfo); 
      } else { 
       // send out a notification for the failed transaction 
       NSNotificationCenter.DefaultCenter.PostNotificationName (new NSString("InAppPurchaseManagerTransacionFailedNotification"), this, userInfo); 
      } 
     } 
    } 

    public void FailedTransaction (SKPaymentTransaction transaction) 
    { 
     if (transaction.Error.Code == 2) // user cancelled 
      Console.WriteLine("User CANCELLED FailedTransaction Code=" + transaction.Error.Code + " " + transaction.Error.LocalizedDescription); 
     else // error! 
      Console.WriteLine("FailedTransaction Code=" + transaction.Error.Code + " " + transaction.Error.LocalizedDescription); 
     FinishTransaction(transaction,false); 
    } 
}} 

在FinishTransaction方法上,如果事务成功,我想将返回的收据插入到我的服务器中(在插入之前,当然需要在苹果服务器上进行验证)。所以在这一点上,我需要访问SKPaymentTransaction.TransactionReceipt,将此收据编码为base64,并将其发送到我的服务器。这只是不行,我不知道为什么。

我的交易观察员:

public class TransactionObserver : SKPaymentTransactionObserver 
{ 
    private InAppPurchaseManager iap; 

    public TransactionObserver (InAppPurchaseManager manager) : base() 
    { 
     iap = manager; 
    } 

    public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions) 
    { 
     foreach (SKPaymentTransaction transaction in transactions) 
     { 
      switch (transaction.TransactionState) 
      { 
      case SKPaymentTransactionState.Purchased: 
       iap.CompleteTransaction (transaction); 
       break; 
       case SKPaymentTransactionState.Failed: 
       iap.FailedTransaction(transaction); 
       break; 
       default: 
       break; 
      } 
     } 

    } 
} 

所以,另一个信息我可以给你的是,我的项目编译,当它试图将应用程序部署到我的设备,它崩溃。

而且,我对xamarin测试频道,因为我已经在使用异步和等待。

所以,如果你看到任何错误,请让我知道。

UPDATE

每次我清理它的工作项目,并停止给这个错误!我不知道为什么这是这样的行为!

+0

我看到被标记为'async'一些方法,但他们似乎没有'await'任何东西(如'FinishTransaction')做的。你看到关于这个的一些警告信息吗? (虽然我认为这不会解决你的问题) – jonathanpeppers

+0

是的,那是因为我之前正在向windows azure移动服务提出请求。但是你很紧张,它不能解决这个问题。 @jonathanpeppers – Daniel

回答

2

这是一个known bug

还有在bug报告workaround:增加“-f”在项目的iOS额外的mTouch参数构建选项页。