由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无效的产品标识符:(null)”

Posted

技术标签:

【中文标题】由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无效的产品标识符:(null)”【英文标题】:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid product identifier: (null)' 【发布时间】:2015-04-22 08:34:41 【问题描述】:

我正在尝试将应用购买添加到我的 xCode 应用程序中,但出现此错误:

* 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“产品标识符无效: (空值)' * 第一次抛出调用栈:(0x184bf82d8 0x19641c0e4 0x184bf8218 0x189597210 0x100066fa8 0x100067018 0x18966d404 0x1896564e0 0x18966cda0 0x18966ca2c 0x189665f68 0x18963918c 0x1898da324 0x1896376a0 0x184bb0240 0x184baf4e4 0x184bad594 0x184ad92d4 0x18e2ef6fc 0x18969efac 0x100069600 0x196a9aa08) libc++abi.dylib: 以 NSException 类型的未捕获异常终止

我已尝试使用 ios 模拟器和我的 iPhone 设备运行我的应用程序。

完整的 ViewController.swift 代码:

import UIKit
import StoreKit

class ViewController: UIViewController, SKPaymentTransactionObserver, SKProductsRequestDelegate

    var product:SKProduct!

    @IBOutlet weak var lastmanstandingButton: UIButton!
    @IBOutlet weak var upgradeProButton: UIButton!

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        lastmanstandingButton.enabled = false
        SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    

        override func didReceiveMemoryWarning() 
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
    

    func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) 
        let products = response.products
        if (products.count != 0)
        
            product = products[0] as! SKProduct;
            //productInfo.text = product.localizedTitle + "\n" + product.localizedDescription
        
    

    func getProductInfo()
        if (SKPaymentQueue.canMakePayments())
            let productID:NSSet = NSSet(object:"com.mi.yaya.inapp1");
            let request:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as Set<NSObject>)
            request.delegate = self;
            request.start()
        
    

    @IBAction func upgradeProButtonAction(sender: AnyObject) 
        let payment:SKPayment = SKPayment(product: product);
        SKPaymentQueue.defaultQueue().addPayment(payment)
    

    func unlockProFeatures()
        lastmanstandingButton.enabled = true
    

    func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) 
        for transaction:AnyObject in transactions 
            if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction
                switch trans.transactionState 
                case .Purchased:
                    self.unlockProFeatures();
                    SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .Failed:
                    SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .Restored:
                    SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
                    break
                default:
                    break
                
            
        
    

用于 IAP 的教程:https://www.youtube.com/watch?v=hnRO87_2GpQ

编辑: 在 iTunes Connect 中,我在我正在创建的应用程序中添加了应用内购买。它说:状态:准备提交

【问题讨论】:

【参考方案1】:

您似乎没有正确设置产品标识符。检查您呼叫getProductInfo 的位置以及ID 是否设置正确。还要检查方法调用的顺序,并确保在正确的时刻发送 ID。

我想指出一些您可能想要改进的行:

您应该将product 设置为可选项,因为如果您的请求没有返回值,您的应用程序将会崩溃 productsRequest 不是一个好的方法名称。相反,您可以使用requestProducts

【讨论】:

productID 正确。我什至已经从 iTunes Connect IAP 复制/粘贴了 productID,并粘贴到了 xCode 项目中。我看不出这里有什么问题。 我确定您设置了正确的 ID,但请通过在 getProductInfo 中设置断点来检查它是否正确发送。【参考方案2】:

我正在回答我自己的问题,因为我找到了使用另一个代码的解决方案:

import UIKit
import StoreKit

class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver 

    var product_id: NSString?;

    @IBOutlet weak var lastmanstandingButton: UIButton!
    @IBOutlet weak var upgradeProButton: UIButton!

    override func viewDidLoad() 
        product_id = "com.mi.yaya.inapp1";
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        lastmanstandingButton.enabled = false
        SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    

        override func didReceiveMemoryWarning() 
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
    

    @IBAction func upgradeProButtonAction(sender: AnyObject) 
        buyConsumable()
    

    func buyConsumable()
        println("About to fetch the products");
        // We check that we are allow to make the purchase.
        if (SKPaymentQueue.canMakePayments())
        
            var productID:NSSet = NSSet(object: self.product_id!);
            var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as Set<NSObject>);
            productsRequest.delegate = self;
            productsRequest.start();
            println("Fething Products");
        else
            println("can't make purchases");
        
    

    // Helper Methods

    func buyProduct(product: SKProduct)
        println("Sending the Payment Request to Apple");
        var payment = SKPayment(product: product)
        SKPaymentQueue.defaultQueue().addPayment(payment);

    


    // Delegate Methods for IAP

    func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) 
        println("got the request from Apple")
        var count : Int = response.products.count
        if (count>0) 
            var validProducts = response.products
            var validProduct: SKProduct = response.products[0] as! SKProduct
            if (validProduct.productIdentifier == self.product_id) 
                println(validProduct.localizedTitle)
                println(validProduct.localizedDescription)
                println(validProduct.price)
                buyProduct(validProduct);
             else 
                println(validProduct.productIdentifier)
            
         else 
            println("nothing")
        
    


    func request(request: SKRequest!, didFailWithError error: NSError!) 
        println("La vaina fallo");
    

    func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!)    
        println("Received Payment Transaction Response from Apple");

        for transaction:AnyObject in transactions 
            if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction
                switch trans.transactionState 
                case .Purchased:
                    println("Product Purchased");
                    SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
                    break;
                case .Failed:
                    println("Purchased Failed");
                    SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
                    break;
                    // case .Restored:
                    //[self restoreTransaction:transaction];
                default:
                    break;
                
            
        

    


来源:https://github.com/ivanacostarubio/swift-in-app-purchase-example

我在我的设备上测试并给了我输出:

About to fetch the products
Fething Products
got the request from Apple
Upgrade PRO
Oppgradere til PRO å få alle funksjoner, fjerne annonser og få fremtidige betalingsoppdateringer gratis.
19
Sending the Payment Request to Apple
Received Payment Transaction Response from Apple
Received Payment Transaction Response from Apple
Product Purchased

【讨论】:

【参考方案3】:

潜在原因:

    您是否为您的 App ID 启用了应用内购买? 您是否有有效的 iTunes 付费应用程序合同? 您是否已为您的产品检查过清仓销售? 是否有任何合同等待批准? 应用内购买已填写所有字段(包括屏幕截图)? 您是否等了 24 小时? 使用真实设备(不是模拟器)? 您是否在注册时使用了完整的产品 ID? 您的产品 ID 是否有任何错误? 在加载购买之前,您是否等待 cordova 的“deviceready”事件? 您是否已提交(并可选择拒绝)您的应用程序二进制文件? 您项目的 .plist Bundle ID 是否与您的 App ID 匹配? 您是否为新的 App ID 生成并安装了新的配置文件? 您是否已将项目配置为使用此新的配置文件进行代码签名? 您的银行详细信息在 iTunes Connect 上是否有效? 您是否尝试过从设备中删除该应用并重新安装? 您的设备是否越狱?如果是这样,您需要恢复越狱才能使 IAP 正常工作。

【讨论】:

以上是关于由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无效的产品标识符:(null)”的主要内容,如果未能解决你的问题,请参考以下文章

由于未捕获的异常而终止应用程序 [UIImageView _isResizable]

由于未捕获的异常而终止应用程序,同时加载视图

由于未捕获的异常“NSInternalInconsistencyException”错误而终止应用程序

“由于未捕获的异常而终止应用程序”在推送视图控制器时崩溃

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序