Dawid
Dawid

Reputation: 715

SKProductsRequest causes crash - Cocos2d and In App Purchase

I have a very strange issue with "In App Purchase" and Cocos2D engine. Everything seems to work well ,and there is no problems with transactions. But when I open and close several timesthe scene in which I use "in app purchase" transactions, the application crashes. Sometimes it happens after a few minutes.

.m file :

In my Init Function:

  if ([SKPaymentQueue canMakePayments]) {
    productsRequest=[[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects: @"xxx.blockads", @"xxx.unlocklevels",nil]];
    productsRequest.delegate = self;
    [productsRequest start];
    } else {
    // 
    }

Other Functions related to the "In App"

-(void) unlock1: (id) sender {

     payment = [SKPayment paymentWithProductIdentifier:@"xxx.blockads"];

     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

     [[SKPaymentQueue defaultQueue] addPayment:payment];

}


-(void) unlock2: (id) sender {

     payment = [SKPayment paymentWithProductIdentifier:@"xxx.unlocklevels"];

     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

     [[SKPaymentQueue defaultQueue] addPayment:payment];

}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {

     SKProduct *validProduct = nil;
     int count = [response.products count];
     if (count > 0) {

          validProduct = [response.products objectAtIndex:0];
     } else if (!validProduct) {

     }

     NSLog(@"Valid products: %@", response.products);
     NSLog(@"invalid products: %@", response.invalidProductIdentifiers);
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {

     for (SKPaymentTransaction *transaction in transactions) {

          switch (transaction.transactionState) {

               case SKPaymentTransactionStatePurchasing:


                                  break;

               case SKPaymentTransactionStatePurchased:
                                   //Something
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                    break;


               case SKPaymentTransactionStateRestored:

                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                    break;

               case SKPaymentTransactionStateFailed:

                    if (transaction.error.code != SKErrorPaymentCancelled) {

                         NSLog(@"An error encounterd");
                    }

                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                    break;

          }
    }
}

Crash Log:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)

Exception Codes: KERN_INVALID_ADDRESS at 0xd0000008
Crashed Thread:  0
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:

0   libobjc.A.dylib                    0x35db9c98 objc_msgSend + 16
1   StoreKit                           0x31c77d96 -[SKProductsRequest handleFinishResponse:returningError:] + 38
2   StoreKit                           0x31c79086 -[SKRequest _requestFinishedNotification:] + 150
3   Foundation                         0x3010f17c _nsnote_callback + 136
4   CoreFoundation                     0x31091208 __CFXNotificationPost_old + 396
5   CoreFoundation                     0x3102bee4 _CFXNotificationPostNotification + 112
6   Foundation                         0x3010c5cc -[NSNotificationCenter postNotificationName:object:userInfo:] + 64
7   AppSupport                         0x325ae44e -[CPDistributedNotificationCenter deliverNotification:userInfo:] + 38
8   AppSupport                         0x325af77a _CPDNDeliverNotification + 198
9   AppSupport                         0x325ae1d0 _XDeliverNotification + 116
10  AppSupport                         0x325a4dd0 migHelperRecievePortCallout + 132
11  CoreFoundation                     0x31099a90 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 20
12  CoreFoundation                     0x3109b838 __CFRunLoopDoSource1 + 160
13  CoreFoundation                     0x3109c606 __CFRunLoopRun + 514
14  CoreFoundation                     0x3102cebc CFRunLoopRunSpecific + 224
15  CoreFoundation                     0x3102cdc4 CFRunLoopRunInMode + 52
16  GraphicsServices                   0x32215418 GSEventRunModal + 108
17  GraphicsServices                   0x322154c4 GSEventRun + 56
18  UIKit                              0x32795d62 -[UIApplication _run] + 398
19  UIKit                              0x32793800 UIApplicationMain + 664
20  ninjaballhd                        0x00003b96 main (main.m:13)
21  ninjaballhd                        0x00003b68 start + 32

Thread 1 name:  Dispatch queue: com.apple.libdispatch-manager
Thread 1:

0   libsystem_kernel.dylib             0x3002afbc kevent + 24
1   libdispatch.dylib                  0x366ee094 _dispatch_mgr_invoke + 672
2   libdispatch.dylib                  0x366ef04a _dispatch_queue_invoke + 86
3   libdispatch.dylib                  0x366ee60a _dispatch_worker_thread2 + 190
4   libsystem_c.dylib                  0x3624358a _pthread_wqthread + 258
5   libsystem_c.dylib                  0x36243bbc start_wqthread + 0


Thread 2:

0   libsystem_kernel.dylib             0x3002a3ec __workq_kernreturn + 8
1   libsystem_c.dylib                  0x362436d8 _pthread_wqthread + 592
2   libsystem_c.dylib                  0x36243bbc start_wqthread + 0

Thread 3 name:  WebThread

Thread 3:

0   libsystem_kernel.dylib             0x30027c00 mach_msg_trap + 20
1   libsystem_kernel.dylib             0x30027758 mach_msg + 44
2   CoreFoundation                     0x3109a2b8 __CFRunLoopServiceMachPort + 88
3   CoreFoundation                     0x3109c562 __CFRunLoopRun + 350
4   CoreFoundation                     0x3102cebc CFRunLoopRunSpecific + 224
5   CoreFoundation                     0x3102cdc4 CFRunLoopRunInMode + 52
6   WebCore                            0x32ccb37a RunWebThread(void*) + 378
7   libsystem_c.dylib                  0x3624230a _pthread_start + 242
8   libsystem_c.dylib                  0x36243bb4 thread_start + 0



Thread 4 name:  AURemoteIO::IOThread

Thread 4:
0   libsystem_kernel.dylib             0x30027c00 mach_msg_trap + 20
1   libsystem_kernel.dylib             0x30027758 mach_msg + 44
2   AudioToolbox                       0x32308824 AURemoteIO::IOThread::Run() + 80
3   AudioToolbox                       0x3230e342 AURemoteIO::IOThread::Entry(void*) + 2
4   AudioToolbox                       0x3224348a CAPThread::Entry(CAPThread*) + 138
5   libsystem_c.dylib                  0x3624230a _pthread_start + 242
6   libsystem_c.dylib                  0x36243bb4 thread_start + 0

Upvotes: 2

Views: 3892

Answers (2)

Matthias Bauch
Matthias Bauch

Reputation: 90117

Most likely this is a memory managment problem. handleFinishResponse:returningError: could be an internal method of an object that gets deallocated because your memory management is wrong.
You dealloc the controller that handles the in app purchase before receiving a response from the IAP. Due to the delayed responses from internet connections the selector is sent to a deallocated object.

There is another question on Stackoverflow with the exact same exception and the reason was a memory management problem.

Use NSZombieEnabled to check if this is the reason for the exception

From cocoadev.com:

  • Double-click an executable in the Executables group of your Xcode project.
  • Click the Arguments tab.
  • In the "Variables to be set in the environment:" section, make a variable called "NSZombieEnabled" and set its value to "YES".

Upvotes: 6

adam
adam

Reputation: 22587

Where is the code for handleFinishResponse:returningError: - if this doesn't exist it makes sense that this is causing the crash....

Also add the following code to your scene in order to stop creating multiple transaction observers:

- (void)onExit {
    [super onExit];
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

Upvotes: 0

Related Questions