我遇到了一些令人困惑的行爲,這些行爲與我的應用內購買還原功能有關。目前,我已將恢復功能鏈接到一個按鈕,當我多次激活它時,它似乎會崩潰。例如,如果我點擊它,恢復,導航到另一個視圖,然後再次點擊恢復,它會崩潰。迅速恢復購買時發生崩潰
任何人都可以檢查我的代碼,看看我是否錯過了盯着我的臉?
import SpriteKit
import StoreKit
class PurchaseView: SKScene, SKPaymentTransactionObserver, SKProductsRequestDelegate{
var instructLabel = SKLabelNode()
var priceLabel = SKLabelNode()
var saleBadgeIcon = SKSpriteNode()
var backIcon = SKSpriteNode()
var restoreIcon = SKSpriteNode()
var blueDiceDemo = SKSpriteNode()
var redDiceDemo = SKSpriteNode()
var greenDiceDemo = SKSpriteNode()
var grayDiceDemo = SKSpriteNode()
var bluePID: String = "dice.blue.add"
var redPID: String = "dice.red.add"
var greenPID: String = "dice.green.add"
var grayPID: String = "dice.gray.add"
private var request : SKProductsRequest!
private var products : [SKProduct] = []
private var blueDicePurchased : Bool = false
private var redDicePurchased : Bool = false
private var greenDicePurchased : Bool = false
private var grayDicePurchased : Bool = false
override func didMoveToView(view: SKView) {
// In-App Purchase
initInAppPurchases()
/*
checkAndActivateGreenColor()
checkAndActivateRedColor()
checkAndActivateGrayColor()
checkAndActivateBlueColor()
*/
createInstructionLabel()
createBackIcon()
createRestoreIcon()
createBlueDicePurchase()
createRedDicePurchase()
createGreenDicePurchase()
createGrayDicePurchase()
checkAndActivateDiceColor(bluePID)
checkAndActivateDiceColor(redPID)
checkAndActivateDiceColor(greenPID)
checkAndActivateDiceColor(grayPID)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let node = nodeAtPoint(location)
if (node == backIcon) {
let gameScene = GameScene(size: self.size)
let transition = SKTransition.doorsCloseVerticalWithDuration(0.5)
gameScene.scaleMode = SKSceneScaleMode.ResizeFill
gameScene.backgroundColor = SKColor.whiteColor()
self.scene!.view?.presentScene(gameScene, transition: transition)
} else if (node == restoreIcon) {
print("restore my purchases")
let alert = UIAlertController(title: "Restore Purchases", message: "", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Restore", style: UIAlertActionStyle.Default) { _ in
self.restorePurchasedProducts()
})
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default) { _ in
})
// Show the alert
self.view?.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
//restorePurchasedProducts()
} else if (node == blueDiceDemo) {
print("buy blue")
if (!blueDicePurchased) {
inAppPurchase(blueDicePurchased, pid: bluePID)
}
} else if (node == redDiceDemo) {
print("buy red")
if (!redDicePurchased) {
inAppPurchase(redDicePurchased, pid: redPID)
}
} else if (node == greenDiceDemo) {
print("buy green")
if (!greenDicePurchased) {
inAppPurchase(greenDicePurchased, pid: greenPID)
}
} else if (node == grayDiceDemo) {
print("buy gray")
if (!grayDicePurchased) {
inAppPurchase(grayDicePurchased, pid: grayPID)
}
}
}
}
func createBlueDicePurchase() {
blueDiceDemo = SKSpriteNode(imageNamed: "dice1_blue")
blueDiceDemo.setScale(0.6)
blueDiceDemo.position = CGPoint(x: CGRectGetMidX(self.frame) + blueDiceDemo.size.width * 2, y: CGRectGetMidY(self.frame))
addChild(blueDiceDemo)
createSaleBadge(blueDiceDemo)
}
func createGrayDicePurchase() {
grayDiceDemo = SKSpriteNode(imageNamed: "dice1_gray")
grayDiceDemo.setScale(0.6)
grayDiceDemo.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
addChild(grayDiceDemo)
createSaleBadge(grayDiceDemo)
}
func createRedDicePurchase() {
redDiceDemo = SKSpriteNode(imageNamed: "dice1_red")
redDiceDemo.setScale(0.6)
redDiceDemo.position = CGPoint(x: CGRectGetMidX(self.frame) - blueDiceDemo.size.width * 2, y: CGRectGetMidY(self.frame))
addChild(redDiceDemo)
createSaleBadge(redDiceDemo)
}
func createGreenDicePurchase() {
greenDiceDemo = SKSpriteNode(imageNamed: "dice1_green")
greenDiceDemo.setScale(0.6)
greenDiceDemo.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame) - blueDiceDemo.size.height * 1.5)
addChild(greenDiceDemo)
createSaleBadge(greenDiceDemo)
}
func createInstructionLabel() {
instructLabel = SKLabelNode(fontNamed: "Helvetica")
instructLabel.text = "Click item to purchase!"
instructLabel.fontSize = 24
instructLabel.fontColor = SKColor.blackColor()
instructLabel.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMaxY(self.frame) - 50)
addChild(instructLabel)
}
func createPurchasedLabel(node: SKSpriteNode) {
let purchasedLabel = SKLabelNode(fontNamed: "Helvetica")
purchasedLabel.text = "purchased"
purchasedLabel.fontSize = 30
purchasedLabel.zPosition = 2
purchasedLabel.fontColor = SKColor.blackColor()
purchasedLabel.position = CGPoint(x: 0, y: -7.5)
node.addChild(purchasedLabel)
}
func createRestoreIcon() {
restoreIcon = SKSpriteNode(imageNamed: "download")
restoreIcon.setScale(0.4)
restoreIcon.position = CGPoint(x: CGRectGetMinX(self.frame) + 30, y: CGRectGetMinY(self.frame) + 30)
addChild(restoreIcon)
}
func createBackIcon() {
backIcon = SKSpriteNode(imageNamed: "remove")
backIcon.setScale(0.5)
backIcon.position = CGPoint(x: CGRectGetMaxX(self.frame) - 30, y: CGRectGetMinY(self.frame) + 30)
addChild(backIcon)
}
func createSaleBadge(node: SKSpriteNode) {
saleBadgeIcon = SKSpriteNode(imageNamed: "badge")
saleBadgeIcon.setScale(0.4)
saleBadgeIcon.zPosition = 2
saleBadgeIcon.position = CGPoint(x: node.size.width/2, y: node.size.height/2)
node.addChild(saleBadgeIcon)
}
func inAppPurchase(dicePurchased: Bool, pid: String) {
let alert = UIAlertController(title: "In-App Purchases", message: "", preferredStyle: UIAlertControllerStyle.Alert)
// Add an alert action for each available product
for (var i = 0; i < products.count; i++) {
let currentProduct = products[i]
if (currentProduct.productIdentifier == pid && !dicePurchased) {
// Get the localized price
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .CurrencyStyle
numberFormatter.locale = currentProduct.priceLocale
// Add the alert action
alert.addAction(UIAlertAction(title: currentProduct.localizedTitle + " " + numberFormatter.stringFromNumber(currentProduct.price)!, style: UIAlertActionStyle.Default) { _ in
// Perform the purchase
self.buyProduct(currentProduct)
})
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default) { _ in
})
// Show the alert
self.view?.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}
}
}
//Initializes the App Purchases
func initInAppPurchases() {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// Get the list of possible purchases
if self.request == nil {
self.request = SKProductsRequest(productIdentifiers: Set(["dice.green.add", "dice.blue.add", "dice.gray.add","dice.red.add"]))
self.request.delegate = self
self.request.start()
}
}
// Request a purchase
func buyProduct(product: SKProduct) {
let payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment)
}
// Restore purchases
func restorePurchasedProducts() {
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
// StoreKit protocoll method. Called when the AppStore responds
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
self.products = response.products
self.request = nil
}
// StoreKit protocoll method. Called when an error happens in the communication with the AppStore
func request(request: SKRequest, didFailWithError error: NSError) {
print(error)
self.request = nil
}
// StoreKit protocoll method. Called after the purchase
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch (transaction.transactionState) {
case .Purchased:
if transaction.payment.productIdentifier == "dice.green.add" {
handleDiceColorPurchase(greenPID)
print("buying green")
} else if transaction.payment.productIdentifier == "dice.blue.add" {
handleDiceColorPurchase(bluePID)
print("buying blue")
} else if transaction.payment.productIdentifier == "dice.red.add" {
handleDiceColorPurchase(redPID)
print("buying red")
} else if transaction.payment.productIdentifier == "dice.gray.add" {
handleDiceColorPurchase(grayPID)
print("buying gray")
} else {
print("Error: Invalid Product ID")
}
queue.finishTransaction(transaction)
case .Restored:
if transaction.payment.productIdentifier == "dice.green.add" {
handleDiceColorPurchase(greenPID)
print("restoring green")
} else if transaction.payment.productIdentifier == "dice.blue.add" {
handleDiceColorPurchase(bluePID)
print("restoring blue")
} else if transaction.payment.productIdentifier == "dice.red.add" {
handleDiceColorPurchase(redPID)
print("restoring red")
} else if transaction.payment.productIdentifier == "dice.gray.add" {
handleDiceColorPurchase(grayPID)
print("restoring gray")
} else {
print("Error: Invalid Product ID")
}
queue.finishTransaction(transaction)
case .Failed:
print("Payment Error: \(transaction.error)")
queue.finishTransaction(transaction)
default:
print("Transaction State: \(transaction.transactionState)")
}
}
}
// Called after the purchase to provide the colored dice feature
func handleDiceColorPurchase(pid: String){
switch(pid) {
case greenPID:
greenDicePurchased = true
greenDiceDemo.alpha = 0.25
greenDiceDemo.removeAllChildren()
createPurchasedLabel(greenDiceDemo)
case redPID:
redDicePurchased = true
redDiceDemo.alpha = 0.25
redDiceDemo.removeAllChildren()
createPurchasedLabel(redDiceDemo)
case grayPID:
grayDicePurchased = true
grayDiceDemo.alpha = 0.25
grayDiceDemo.removeAllChildren()
createPurchasedLabel(grayDiceDemo)
case bluePID:
blueDicePurchased = true
blueDiceDemo.alpha = 0.25
blueDiceDemo.removeAllChildren()
createPurchasedLabel(blueDiceDemo)
default:
print("No action taken, incorrect PID")
}
checkAndActivateDiceColor(pid)
// persist the purchase locally
NSUserDefaults.standardUserDefaults().setBool(true, forKey: pid)
}
func checkAndActivateDiceColor(pid: String){
if NSUserDefaults.standardUserDefaults().boolForKey(pid) {
switch(pid) {
case greenPID:
greenDicePurchased = true
greenDiceDemo.alpha = 0.25
greenDiceDemo.removeAllChildren()
createPurchasedLabel(greenDiceDemo)
case redPID:
redDicePurchased = true
redDiceDemo.alpha = 0.25
redDiceDemo.removeAllChildren()
createPurchasedLabel(redDiceDemo)
case grayPID:
grayDicePurchased = true
grayDiceDemo.alpha = 0.25
grayDiceDemo.removeAllChildren()
createPurchasedLabel(grayDiceDemo)
case bluePID:
blueDicePurchased = true
blueDiceDemo.alpha = 0.25
blueDiceDemo.removeAllChildren()
createPurchasedLabel(blueDiceDemo)
default:
print("No action taken, incorrect PID")
}
}
}
}
當它崩潰,沒有太多的信息,我可以破譯。我得到一個錯誤,說明我的AppDelegate類EXC_BAD_ACCESS(代碼= 1,地址= 0xc),並突出顯示綠色,說明入隊從com.apple.root.default-qos.overcommit(線程4)
任何幫助表示讚賞!
什麼是印刷在控制檯中? – nhgrif
這些是最後的意見:'恢復綠色 恢復紅色 恢復藍 (lldb)' – tbaldw02