0

所以我一直在尝试在我的应用程序中设置应用程序购买,但遇到了一个我不知道如何解决的问题。我与 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 beta 频道上,因为我已经在使用 async 和 await。

因此,如果您发现任何问题,请告诉我。

更新

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

4

1 回答 1

2

这是一个已知的错误

错误报告中还有一个解决方法:在项目的 iOS 构建选项页面中将“-f”添加到附加的 mtouch 参数中。

于 2013-05-20T10:03:13.213 回答