SKProductRequestDelegate离开视图时崩溃

时间:2016-05-24 01:25:43

标签: ios swift sprite-kit

我已经实施了一个IAP场景OptionsPage: SKScene,用户可以在其中购买“移除广告”和游戏币等。但是,如果我从MenuScene: SKScene转到OptionsPage: SKScene并返回菜单它很快就与Thread 1: EXC_BAD_ACCESS (code=1, address=0x216d0716)崩溃,而底部记录中唯一的东西是(lldb)。

我在SKPaymentQueue.defaultQueue().removeTransactionObserver(self)中呼叫willMoveFromView()

在我的didMoveToView中,我调用setIAP()函数(如下所示)。

在经常猛烈抨击桌子(第一次处理IAP)之后,我认为它正在发生,因为我设置了request.delegate = self所以当我进入场景时request.start()运行但是因为我很快离开现场request.delegate = self已不再有效。

我认为删除事务观察者会在willMoveFromView中处理这个问题。我怎样才能解决这个问题呢?

以下是我在touchesBegan()

中致电购买的方式
if removeAds.containsPoint(location) {
                for product in list {
                    let prodID = product.productIdentifier
                    if (prodID == "removeAds") {
                        p = product
                        buyProduct()
                        break
                    }
                }
            }

以下是IAP部分的内容

// MARK: In App Purchases

func setIAP() {
    // Set IAPS
    if(SKPaymentQueue.canMakePayments()) {
        print("IAP is enabled, loading")
        let productID:NSSet = NSSet(objects: "removeAds, 10000coins")
        let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
        request.delegate = self
        request.start()
    } else {
        print("please enable IAPS")
    }
}

var list = [SKProduct]()
var p = SKProduct()

func buyProduct() {
    print("buy " + p.productIdentifier)
    let pay = SKPayment(product: p)
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}

func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
    print("product request")
    let myProduct = response.products

    for product in myProduct {
        print("Product added: \(product.productIdentifier), \(product.localizedTitle), \(product.localizedDescription), \(product.price)")

        list.append(product)
    }
}

func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {

    print("transactions restored")
    for transaction in queue.transactions {
        let t: SKPaymentTransaction = transaction

        let prodID = t.payment.productIdentifier as String

        switch prodID {
        case "removeAds":
            defaults.setBool(true, forKey: "removeAdsPurchased")

        default:
            print("IAP not setup")
        }
    }

    let alert = UIAlertController(title: "Thank You", message: "Thankyou for your purchase.", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
    self.view?.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}

func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    print("add paymnet")

    for transaction:AnyObject in transactions {
        let trans = transaction as! SKPaymentTransaction
        print(trans.error)

        switch trans.transactionState {

        case .Purchased, .Restored:
            print(p.productIdentifier)

            let prodID = p.productIdentifier as String

            switch prodID {
            case "removeAds":

                defaults.setBool(true, forKey: "removeAdsPurchased")

            case "10000Coins":

                defaults.setInteger(bank + 10000, forKey: "bankValue")
                bank = defaults.integerForKey("bankValue")

            default:
                print("IAP not setup")
            }

            queue.finishTransaction(trans)
            break;

        case .Failed:
            print("buy error")
            queue.finishTransaction(trans)
            break;

        default:
            print("default")
            break;
        }
    }
}

func finishTransaction(trans:SKPaymentTransaction) {
    print("Transaction finished")
}

func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
    print("Transaction removed")
}

1 个答案:

答案 0 :(得分:0)

我解决这个问题的方式,因为没有反馈,但是非常乏味,但如下:

我没有将两个场景组合在一起,而是组合了菜单和选项场景,以便在点击选项按钮时,它会运行一个动作,将菜单节点从屏幕上滑出,并将选项滑动到屏幕上。这样request.delegate = self不会改变,从而避免崩溃。然后唯一的问题是,如果我启动应用程序并在request.start完成之前快速按下播放按钮移动到游戏场景,它将同样崩溃。所以我创建了一个加载启动画面,在菜单场景didMoveToView中运行2秒,这样它就有足够的时间在允许交互之前获取所有数据。

我很想听到一个更简单的解决方案,但凭借我的经验,这就是我想出来的。