我已经实施了一个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")
}
答案 0 :(得分:0)
我解决这个问题的方式,因为没有反馈,但是非常乏味,但如下:
我没有将两个场景组合在一起,而是组合了菜单和选项场景,以便在点击选项按钮时,它会运行一个动作,将菜单节点从屏幕上滑出,并将选项滑动到屏幕上。这样request.delegate = self
不会改变,从而避免崩溃。然后唯一的问题是,如果我启动应用程序并在request.start
完成之前快速按下播放按钮移动到游戏场景,它将同样崩溃。所以我创建了一个加载启动画面,在菜单场景didMoveToView
中运行2秒,这样它就有足够的时间在允许交互之前获取所有数据。
我很想听到一个更简单的解决方案,但凭借我的经验,这就是我想出来的。