应用程序购买中的xamarin内存泄漏

时间:2013-05-16 21:00:29

标签: ios xamarin.ios in-app-purchase xamarin

所以我一直试图在我的应用程序中设置应用程序购买并遇到一个我不知道如何解决的问题。我正在和xamarin一起工作,我跟着他们In app purchase guide了解如何购买消耗品。

在我尝试获取apple返回的交易收据之前,一切都很顺利。每次我从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;
            }
        }

    }
}

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

此外,由于我已经在使用async并等待,我正在使用xamarin beta频道。

所以,如果您发现任何错误,请告诉我。

更新

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

1 个答案:

答案 0 :(得分:2)

这是known bug

错误报告中还有一个workaround:将“-f”添加到项目的iOS Build options页面中的其他mtouch参数。