I've searched the internet for help on this but to no avail. My app is live on the app store and a minority of users are reporting the app freezing on them and crashing after making an In App Purchase (the only IAP in my game, it basically unlocks the full version). Even when they restart their device and try to continue, it crashes again. I haven't been able to reproduce the crash - here is the crash report:
{"bug_type":"109","os_version":"iPhone OS 9.2 (13C75)","timestamp":"2015-12-12 15:34:59.59 +0000","build_version":"1","app_name":"MyApp","bundleID":"com.MyName.MyApp","name":"MyApp","is_first_party":false,"app_version":"1.0","share_with_app_devs":true,"slice_uuid":"7abb6a6c-91be-3da0-af0f-2cc21f9a6b83","adam_id":1021569826}
Incident Identifier: 59B078E3-ABC9-47C7-A3BE-6311BBB968F6
CrashReporter Key: b30d57098eecd5a7dfcd44f3a04cfb01bdef557f
Hardware Model: iPad2,5
Process: MyApp [977]
Path: /private/var/mobile/Containers/Bundle/Application/EFAB47F6-F1A3-42A4-A6F1-8A038932ED86/MyApp.app/MyApp
Identifier: com.MyName.MyApp
Version: 1 (1.0)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2015-12-12 15:34:59.59 +0000
Launch Time: 2015-12-12 15:30:02.02 +0000
OS Version: iOS 9.2 (13C75)
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000e7ffdefe
Triggered by Thread: 0
Filtered syslog:
None found
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 MyApp 0x001f8cb8 function signature specialization <Arg[0] = Dead and Owned To Guaranteed, Arg[1] = Owned To Guaranteed> of MyApp.IAPHelper.paymentQueue (MyApp.IAPHelper)(__ObjC.SKPaymentQueue, updatedTransactions : [__ObjC.SKPaymentTransaction]) -> () (IAPHelper.swift:0)
1 MyApp 0x001f59a8 @objc MyApp.IAPHelper.paymentQueue (MyApp.IAPHelper)(__ObjC.SKPaymentQueue, updatedTransactions : [__ObjC.SKPaymentTransaction]) -> () (IAPHelper.swift:0)
2 StoreKit 0x2e7c1a80 __NotifyObserverAboutChanges + 82
3 CoreFoundation 0x25464630 CFArrayApplyFunction + 34
4 StoreKit 0x2e7c1a1c -[SKPaymentQueue _notifyObserversAboutChanges:sendUpdatedDownloads:] + 126
5 StoreKit 0x2e7c2318 -[SKPaymentQueue _processUpdates:trimUnmatched:sendUpdatedDownloads:] + 1042
6 StoreKit 0x2e7c2ca6 -[SKPaymentQueue _updatePaymentsForMessage:] + 120
7 StoreKit 0x2e7c1938 __44-[SKPaymentQueue _handleMessage:connection:]_block_invoke + 142
8 libdispatch.dylib 0x250c9b5a _dispatch_call_block_and_release + 8
9 libdispatch.dylib 0x250c9b46 _dispatch_client_callout + 20
10 libdispatch.dylib 0x250d7ee0 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1522
11 CoreFoundation 0x255133fc __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 6
12 CoreFoundation 0x255118f6 __CFRunLoopRun + 1572
13 CoreFoundation 0x25464bf8 CFRunLoopRunSpecific + 518
14 CoreFoundation 0x254649e4 CFRunLoopRunInMode + 106
15 GraphicsServices 0x266b0ac8 GSEventRunModal + 158
16 UIKit 0x296f4ba0 UIApplicationMain + 142
17 MyApp 0x0018bc24 main (AppDelegate.swift:12)
18 libdyld.dylib 0x25113872 start + 0
Thread 1 name: Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0 libsystem_kernel.dylib 0x251e6320 kevent_qos + 24
1 libdispatch.dylib 0x250de098 _dispatch_mgr_invoke + 254
2 libdispatch.dylib 0x250dddf6 _dispatch_mgr_thread$VARIANT$mp + 36
Thread 2 name: com.apple.NSURLConnectionLoader
Thread 2:
0 libsystem_kernel.dylib 0x251d0c24 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x251d0a28 mach_msg + 38
2 CoreFoundation 0x25513354 __CFRunLoopServiceMachPort + 134
3 CoreFoundation 0x255116dc __CFRunLoopRun + 1034
4 CoreFoundation 0x25464bf8 CFRunLoopRunSpecific + 518
5 CoreFoundation 0x254649e4 CFRunLoopRunInMode + 106
6 CFNetwork 0x25aa781e +[NSURLConnection(Loader) _resourceLoadLoop:] + 484
7 Foundation 0x25d69164 __NSThread__start__ + 1146
8 libsystem_pthread.dylib 0x2528985a _pthread_body + 136
9 libsystem_pthread.dylib 0x252897ce _pthread_start + 108
10 libsystem_pthread.dylib 0x25287724 thread_start + 6
Thread 3 name: com.apple.CFSocket.private
Thread 3:
0 libsystem_kernel.dylib 0x251e4f14 __select + 20
1 CoreFoundation 0x255187a2 __CFSocketManager + 564
2 libsystem_pthread.dylib 0x2528985a _pthread_body + 136
3 libsystem_pthread.dylib 0x252897ce _pthread_start + 108
4 libsystem_pthread.dylib 0x25287724 thread_start + 6
Thread 4:
0 libsystem_kernel.dylib 0x251e588c __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x25287b34 _pthread_wqthread + 1034
2 libsystem_pthread.dylib 0x25287718 start_wqthread + 6
Thread 5:
0 libsystem_kernel.dylib 0x251e588c __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x25287b34 _pthread_wqthread + 1034
2 libsystem_pthread.dylib 0x25287718 start_wqthread + 6
Thread 6:
0 libsystem_kernel.dylib 0x251e588c __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x25287b34 _pthread_wqthread + 1034
2 libsystem_pthread.dylib 0x25287718 start_wqthread + 6
Thread 0 crashed with ARM Thread State (32-bit):
r0: 0x00000000 r1: 0x3bc6d0b0 r2: 0x00000000 r3: 0x00000000
r4: 0x00000000 r5: 0x17222bc2 r6: 0x15ea4330 r7: 0x003fdaf0
r8: 0x1736bce0 r9: 0x00000000 r10: 0x003fdbcc r11: 0xffffffff
ip: 0xf6535949 sp: 0x003fd934 lr: 0x001f7478 pc: 0x001f8cb8
cpsr: 0x60000010
Binary Images:
<not included for reasons of brevity>
The method referenced as causing the crash is as follows:
public func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch (transaction.transactionState) {
case .Purchased:
completeTransaction(transaction)
break
case .Failed:
failedTransaction(transaction)
break
case .Restored:
restoreTransaction(transaction)
break
case .Deferred:
break
case .Purchasing:
break
}
}
}
I'm not sure where to begin really as the code in paymentQueue: updatedTransactions
looks ok to me and was in fact taken direct from a Ray Wenderlich tutorial on IAPs: http://www.raywenderlich.com/105365/in-app-purchases-tutorial-getting-started
This in particular is puzzling me:
function signature specialization <Arg[0] = Dead and Owned To Guaranteed, Arg[1] = Owned To Guaranteed>
What does that mean?
Anybody have any ideas? Or advice on how to reproduce the crash? Because it's only happened a handful of times, could it be something to do with the user's device or Apple's IAP handling, or is it definitely my code?
Thanks in advance!
Edit:
In response to Alpesh's answer, my function now looks like this:
public func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
for transaction in transactions {
switch (transaction.transactionState) {
case .Purchased:
self.completeTransaction(transaction)
break
case .Failed:
self.failedTransaction(transaction)
break
case .Restored:
self.restoreTransaction(transaction)
break
case .Deferred:
break
case .Purchasing:
break
}
}
}
}