App crashed with UITabBarController and in app purchases

My app used in app purchases and my links are here .

When I download products from the server block, at the same time I switch to another tab inside the UITabBarController and the application crashes when loading products

This is my code.

//Load products from server [[LAInAppHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) { if (success) { // even i do nothing in here app till crashed } }]; 

If I delete these lines, I can switch between any tab. Nothing throws the application on crash, even I can turn on Zombie objects. Just bad access

+4
source share
1 answer

There is a problem with the implementation of LAInAppHelper in the manual that you linked : the helper considers your application as non-competitive.

Here's what happens: a shared instance of LAInAppHelper has a sharedInstance to which _completionHandler belongs (by the way).

The requestProductsWithCompletionHandler: method assigns _completionHandler copy of the passed block. This is normal for the first request, but if another request is "in flight", the completion block of this other request will be issued by ARC due to this reassignment. If the tab you are switching to launches a parallel request, the initial request returns to the issued block, causing undefined behavior and possibly fail.

To fix this problem, you need to split the class into two parts containing elements common to all requests (namely _productIdentifiers and _purchasedProductIdentifiers ) and specific to the request ( _productsRequest and _completionHandler ).

The first class instance (let it be called LAInAppHelper ) remains common; instances of the second class (let it be called LAInAppHelperRequest ) are created by request inside the requestProductsWithCompletionHandler: method.

 -(id)initWithHelper:(LAInAppHelper*)helper andCompletionHandler:(RequestProductsCompletionHandler)completionHandler { if (self = [super init]) { _completionHandler = [completionHandler copy]; _productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:helper.productIdentifiers]; // You will need to make productIdentifiers a property _productsRequest.delegate = self; [_productsRequest start]; } return self; } 

You will need to create a block that also wraps _completionHandler as follows:

 - (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler { __block LAInAppHelperRequest *req = [[LAInAppHelperRequest alloc] initWithHelper:self andCompletionHandler:^(BOOL success, NSArray *products) { completionHandler(success, products); req = nil; }]; } 
+3
source

Source: https://habr.com/ru/post/1492007/


All Articles