ios - Store Kit crashes on 2nd request -


i building first store kit app , have crash issue:

the app sprite kit game

in mainmenuscene.swift allocate removeadbutton
when tapped call initpurchaseremoveads() function

mainmenuscene.swifte = skpaymentqueue.defaultqueue()

    func initpurchaseremoveads() {         let actionrotate = skaction.rotatebyangle(cgfloat(m_2_pi), duration: 0.1)         let spin = skaction.repeatactionforever(actionrotate)         self.loadingwheel.runaction(spin)         self.loadingwheel.hidden = false         nsnotificationcenter.defaultcenter().postnotificationname(keyvaluekeyclassification.notificationbuyremovead.rawvalue, object: nil, userinfo: nil)     } 

gameviewcontroller.swift

var request : skproductsrequest? var queue : skpaymentqueue. = skpaymentqueue.defaultqueue()  // called through notification (works!) func initpurchase(notification: nsnotification) {     println("user clicked remove ads")     if skpaymentqueue.canmakepayments() {         println("user can make payments")         self.request = skproductsrequest(productidentifiers: nsset(object: purchaseclassification.removeadid.rawvalue string))         self.request?.delegate = self         self.request?.start()     } else {         println("user cannot make payments")     } }  func restorepurchases() {     skpaymentqueue.defaultqueue().restorecompletedtransactions() }  func purchase(product : skproduct) {     let payment = skpayment(product: product)     skpaymentqueue.defaultqueue().addtransactionobserver(self)     skpaymentqueue.defaultqueue().addpayment(payment) }  func productsrequest(request: skproductsrequest!, didreceiveresponse response: skproductsresponse!) {     var adprodfound : bool = false     var count = response.products.count     if count > 0 {         p in response.products {             if p skproduct {                 var prod = p skproduct                 if prod.productidentifier == purchaseclassification.removeadid.rawvalue string {                     println("remove ad product available")                     adprodfound = true                     purchase(prod)                 }             }         }     }      if !adprodfound {         println("remove ad product not available")     } }  func paymentqueuerestorecompletedtransactionsfinished(queue: skpaymentqueue!) {     println("received restored transactions")      t in queue.transactions {         if t skpaymenttransaction {             var trans = t skpaymenttransaction             if trans.transactionstate == skpaymenttransactionstate.restored {                 println("transactionstate = restored")                 removeads()                 break              }         }     }  }   func paymentqueue(queue: skpaymentqueue!, updatedtransactions transactions: [anyobject]!) {     t in queue.transactions {         if t skpaymenttransaction {             var trans = t skpaymenttransaction             switch trans.transactionstate {             case .purchasing:                break             case .purchased:                 removeads()                 skpaymentqueue.defaultqueue().finishtransaction(trans)                  break            case .restored:                 skpaymentqueue.defaultqueue().finishtransaction(trans)            case .failed:                 if trans.error.code != skerrorpaymentcancelled {                         println("transaction state -> cancelled")                 }                 stopwheel()                 skpaymentqueue.defaultqueue().finishtransaction(trans)                 break             default:                 stopwheel()                 skpaymentqueue.defaultqueue().finishtransaction(trans)             }         }     } }  func stopwheel() {     println("stop wheel") 

nsnotificationcenter.defaultcenter().postnotificationname(keyvaluekeyclassification.notificationstopwheel.rawvalue, object: nil, userinfo: nil) }

func removeads() {     stopwheel()     nsuserdefaults.standarduserdefaults().setbool(true, forkey: keyvaluekeyclassification.keyadsremoved.rawvalue)     nsnotificationcenter.defaultcenter().postnotificationname(keyvaluekeyclassification.notificationremoveads.rawvalue, object: nil, userinfo: nil) } 

problem
* purchase works fine when done once * app crashes if abort purchase (wheel stops spinning, fine) , tap removeads button again

error reproduction:

  • click remove ad purchase
  • cancel purchase
  • click remove ad purchase again

output:

user clicked remove ads user can make payments remove ad product available stop wheel user clicked remove ads user can make payments (lldb) bt thread #1: tid = 0x3186, 0x0000000102abd00b libobjc.a.dylib`objc_msgsend + 11, queue = 'com.apple.main-thread', stop reason = exc_bad_access (code=exc_i386_gpflt)     frame #0: 0x0000000102abd00b libobjc.a.dylib`objc_msgsend + 11     frame #1: 0x000000010084eeee storekit`__34-[skproductsrequest _handlereply:]_block_invoke + 52     frame #2: 0x0000000107070ba6 libdispatch.dylib`_dispatch_call_block_and_release + 12     frame #3: 0x000000010708e7f4 libdispatch.dylib`_dispatch_client_callout + 8     frame #4: 0x00000001070778fb libdispatch.dylib`_dispatch_main_queue_callback_4cf + 949     frame #5: 0x00000001012e9fe9 corefoundation`__cfrunloop_is_servicing_the_main_dispatch_queue__ + 9     frame #6: 0x00000001012aceeb corefoundation`__cfrunlooprun + 2043     frame #7: 0x00000001012ac486 corefoundation`cfrunlooprunspecific + 470     frame #8: 0x00000001031819f0 graphicsservices`gseventrunmodal + 161     frame #9: 0x000000010176e420 uikit`uiapplicationmain + 1282   * frame #10: 0x000000010061a3ae shapesly`top_level_code + 78 @ appdelegate.swift:14     frame #11: 0x000000010061a3ea shapesly`main + 42 @ appdelegate.swift:0     frame #12: 0x00000001070c3145 libdyld.dylib`start + 1 (lldb)  

error:

[app.gameviewcontroller retain]: message sent deallocated instance 0x7fc2fc845880 

i believe problem skproductsrequest not being retained.

the best solution move storekit logic helper class:

class storekithelper: nsobject,skproductsrequestdelegate, skpaymenttransactionobserver, skrequestdelegate { var request : skproductsrequest? var queue : skpaymentqueue = skpaymentqueue.defaultqueue()   class var defaulthelper : storekithelper {     struct static {         static let instance : storekithelper = storekithelper()     }      return static.instance }  override init() {     super.init() }   func initpurchase() {     println("user clicked remove ads")     if skpaymentqueue.canmakepayments() {         println("user can make payments")         self.request = skproductsrequest(productidentifiers: nsset(object: purchaseclassification.removeadid.rawvalue string))         self.request?.delegate = self         self.request?.start()     } else {         println("user cannot make payments")     } }  ... 

you can init purchase without notifications so:

storekithelper.defaulthelper.initpurchase() 

this way can sure properties retained , above error not reoccur.


Comments

Popular posts from this blog

javascript - Any ideas when Firefox is likely to implement lengthAdjust and textLength? -

matlab - "Contour not rendered for non-finite ZData" -

delphi - Indy UDP Read Contents of Adata -