Ich arbeite an einigen IAPs using this tutorial.Completion Handler verursacht EXC_BAD_ACCESS, wenn dieselbe Methode zweimal aufgerufen wird
Zuerst hole ich die Produkte mit diesem:
-(void)fetchAvailableProductsFirstLoad:(BOOL)firstTimeLoading {
[[IAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) { ...
Der Helfer läuft der folgende:
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
@synchronized(self) {
// 1
_completionHandler = [completionHandler copy];
// 2
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
}
Wenn die Produkte zurückgegeben werden oder nicht die folgenden genannt:
#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(@"Loaded list of products...");
_productsRequest = nil;
NSArray * skProducts = response.products;
for (SKProduct * skProduct in skProducts) {
NSLog(@"Found product: %@ %@ %0.2f",
skProduct.productIdentifier,
skProduct.localizedTitle,
skProduct.price.floatValue);
}
_completionHandler(YES, skProducts);
_completionHandler = nil;
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"Failed to load list of products.");
NSLog(@"Error: %@",error);
_productsRequest = nil;
_completionHandler(NO, nil);
_completionHandler = nil;
}
Ausgabe
Das Problem, das wir haben, ist, wenn der Benutzer einen Abruf oder Produkte zweimal startet. Zum Beispiel werden die Fetch-Produkte auf der ViewDidLoad aufgerufen, aber wenn der Benutzer eine schlechte/langsame Verbindung hat und weg navigiert und dann zurück zum Controller. Der erste Abruf wird nicht abgebrochen, daher werden zwei ausgeführt.
Ich glaube, das Problem ist, wenn die zweite zurückgegeben wird und der Zeiger geändert hat/nicht vorhanden/beschädigt ist.
Der EXC_BAD_ACCESS Code 2 Fehler tritt auf der entsprechenden Zeile:
_completionHandler(YES, skProducts);
ODER
_completionHandler(NO, nil);
Danke, ich habe Teile von beiden Antworten verwendet, aber das war am nächsten. Ich fügte auch eine zusätzliche Methode hinzu '- (void) cancelProductRequest { [_productsRequest cancel]; _productsRequest = Null; } ', die die aktuelle Anfrage abbricht, wenn sie von diesem Controller weg navigieren, um dort zu speichern, wo immer mehrere Anfragen sind. – StuartM
Great @StuartM, definitiv am besten, um die Anfrage abzubrechen, wenn Sie es nicht brauchen. Froh, dass ich helfen konnte! – stefandouganhyde