2010-07-24 27 views
16

Utilizo el siguiente código para solicitar una lista de productos según la Guía de programación de compras en la aplicación. Solía ​​funcionar bien en mi aplicación de iPhone, sin embargo, ahora falla cada vez que se solicita la lista de productos. El método delegado (void)productsRequest:(SKProductsRequest **)request didReceiveResponse:(SKProductsResponse **)response nunca se llama.StoreKit SKProductsRequest Crash

SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"my.product.identifier"]]; 
[request setDelegate:self]; 
[request start]; 

Como dije, funcionó perfectamente bien, luego simplemente dejó de funcionar. Este es el bloqueo que ocurre cuando se llama al código anterior.

Exception Type: EXC_BAD_ACCESS (SIGBUS) 
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000011 
Crashed Thread: 0 

Thread 0 Crashed: 
0 libobjc.A.dylib     0x000034f8 objc_msgSend + 24 
1 StoreKit      0x00003e18 -[SKProductsRequest handleFinishResponse:returningError:] + 40 
2 StoreKit      0x000050c4 -[SKRequest _requestFinishedNotification:] + 152 
3 Foundation      0x00019b9a _nsnote_callback + 150 
4 CoreFoundation     0x0006c2de __CFXNotificationPost_old + 390 
5 CoreFoundation     0x0001ab32 _CFXNotificationPostNotification + 122 
6 Foundation      0x000048e4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 64 
7 AppSupport      0x0000bb42 -[CPDistributedNotificationCenter deliverNotification:userInfo:] + 38 
8 AppSupport      0x0000cf66 _CPDNDeliverNotification + 198 
9 AppSupport      0x0000ba4a _XDeliverNotification + 110 
10 AppSupport      0x00002e82 migHelperRecievePortCallout + 122 
11 CoreFoundation     0x000742ac __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 22 
12 CoreFoundation     0x000761d6 __CFRunLoopDoSource1 + 158 
13 CoreFoundation     0x0007718e __CFRunLoopRun + 574 
14 CoreFoundation     0x0001e0bc CFRunLoopRunSpecific + 220 
15 CoreFoundation     0x0001dfca CFRunLoopRunInMode + 54 
16 GraphicsServices    0x00003f88 GSEventRunModal + 188 
17 UIKit       0x00007b40 -[UIApplication _run] + 564 
18 UIKit       0x00005fb8 UIApplicationMain + 964 
19 myapp       0x00002fae main (main.m:13) 
20 myapp       0x00002f58 start + 32 

Thread 1: 
0 libSystem.B.dylib    0x00034e84 kevent + 24 
1 libSystem.B.dylib    0x00102a48 _dispatch_mgr_invoke + 88 
2 libSystem.B.dylib    0x00102494 _dispatch_queue_invoke + 96 
3 libSystem.B.dylib    0x00102634 _dispatch_worker_thread2 + 120 
4 libSystem.B.dylib    0x0008b53c _pthread_wqthread + 392 
5 libSystem.B.dylib    0x00082b6c start_wqthread + 0 

Thread 2: 
0 libSystem.B.dylib    0x00000ab0 mach_msg_trap + 20 
1 libSystem.B.dylib    0x00002f94 mach_msg + 60 
2 CoreFoundation     0x00074b18 __CFRunLoopServiceMachPort + 88 
3 CoreFoundation     0x000770e0 __CFRunLoopRun + 400 
4 CoreFoundation     0x0001e0bc CFRunLoopRunSpecific + 220 
5 CoreFoundation     0x0001dfca CFRunLoopRunInMode + 54 
6 WebCore       0x0000370c RunWebThread(void*) + 552 
7 libSystem.B.dylib    0x0008af80 _pthread_start + 364 
8 libSystem.B.dylib    0x0007d014 thread_start + 0 

Thread 3: 
0 libSystem.B.dylib    0x00000ab0 mach_msg_trap + 20 
1 libSystem.B.dylib    0x00002f94 mach_msg + 60 
2 CoreFoundation     0x00074b18 __CFRunLoopServiceMachPort + 88 
3 CoreFoundation     0x000770e0 __CFRunLoopRun + 400 
4 CoreFoundation     0x0001e0bc CFRunLoopRunSpecific + 220 
5 CoreFoundation     0x0001dfca CFRunLoopRunInMode + 54 
6 Foundation      0x0003c316 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 210 
7 Foundation      0x0000c612 -[NSThread main] + 42 
8 Foundation      0x00092140 __NSThread__main__ + 908 
9 libSystem.B.dylib    0x0008af80 _pthread_start + 364 
10 libSystem.B.dylib    0x0007d014 thread_start + 0 

Thread 4: 
0 libSystem.B.dylib    0x00029f24 select$DARWIN_EXTSN + 20 
1 CoreFoundation     0x0007aa54 __CFSocketManager + 340 
2 libSystem.B.dylib    0x0008af80 _pthread_start + 364 
3 libSystem.B.dylib    0x0007d014 thread_start + 0 

No sé qué está causando el accidente objc_msgSend, o cómo se relaciona con StoreKit. Tampoco tengo idea de qué agregué o cambié lo que hizo que este código simple dejara de funcionar.

Respuesta

48

Una explicación muy probable es si el objeto que estableció como delegado para el objeto SKProductRequest podría haberse desasignado.

Es posible que la solicitud demore algunos segundos en completarse, y esto puede haber pasado la vida útil de su objeto delegado, por lo que es posible que desee asegurarse de que se mantenga por suficiente tiempo.

+0

De hecho, ese era el problema. Esto fue resuelto hace un tiempo con aproximadamente la misma respuesta, de alguna manera que parece haber desaparecido. – ttarik

+0

Hombre fabuloso ... U ahorró mucho de mi tiempo ... –

+0

Está bien, entiendo que el delegado podría estar desasignado, pero ¿cómo lo arreglaría? – impression7vx

3

La respuesta anterior es técnicamente correcta, pero no está completa. Como dijo Megastep, "el objeto que estableces como delegado para SKProductsRequest ya puede haber sido desasignado". Por lo tanto, está enviando un mensaje a un objeto que ya ha sido desasignado. Ahora la respuesta real:

- (void)requestProUpgradeProductData { 
    NSSet *productIdentifiers = //Your Product IDs go here 

    productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; 
    productsRequest.delegate = self; 
    [productsRequest start]; 

    // we will release the request object in the delegate callback 
} 

#pragma mark - 
#pragma mark SKProductRequest Delegate Methods 

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse(SKProductsResponse *)response { 
self.products = response.products; 
//NSLog(@"%i",[products count]); 
proUpgradeProduct = [products count] == 4 ? [[products objectAtIndex:0] retain] : nil; 
if (proUpgradeProduct) 
{ 
    //Do your stuff here... 
} 

for (NSString *invalidProductId in response.invalidProductIdentifiers) 
{ 
    //NSLog(@"Invalid product id: %@" , invalidProductId); 
} 

// finally release the reqest we alloc/init’ed in requestProUpgradeProductData 
[productsRequest release]; 

[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil]; 
} 

Así que, básicamente, como se puede ver por encima de que no es necesario para liberar productsRequest porque ya está siendo liberado en el método delegado de devolución de llamada. De nuevo, no necesita llamar a productsRequest Release o establecerlo como Nil en el método viewDidUnload/dealloc porque podría causar un bloqueo si descarta la vista antes de que se llame al método de devolución de llamada.