我的应用程序用于购买应用程序,我的引用是here。
当我按块从服务器加载产品时,同时我切换到UITabBarController内的其他选项卡,加载产品时应用崩溃
这是我的代码
//Load products from server
[[LAInAppHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
// even i do nothing in here app till crashed
}
}];
如果删除此行,则可以在任何选项卡之间切换。崩溃时应用程序不会抛出任何异常,即使我启用了Zombie对象也是如此。不好访问
最佳答案
tutorial that you linked中的LAInAppHelper
的实现存在问题:帮助程序将您的应用程序视为非并行应用程序。
这是怎么回事:LAInAppHelper
的共享实例有一个sharedInstance
,它拥有_completionHandler
(除其他外)。requestProductsWithCompletionHandler:
方法为_completionHandler
分配了已传递的块的副本。对于第一个请求,这是可以的,但是如果另一个请求处于“运行中”状态,则由于此重新分配,ARC将释放该另一个请求的完成块。如果切换到的选项卡启动并发请求,则初始请求将返回到已释放的块,从而导致不确定的行为,甚至可能导致崩溃。
要解决此问题,您需要将类分为两部分-一部分包含所有请求通用的项(即_productIdentifiers
和_purchasedProductIdentifiers
)和特定于请求的项(_productsRequest
和_completionHandler
)。
第一类的实例(我们将其称为LAInAppHelper
)保持共享;第二类的实例(我们将其称为LAInAppHelperRequest
)是在requestProductsWithCompletionHandler:
方法内按请求创建的。
-(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;
}
您还需要创建一个包装
_completionHandler
的块,如下所示:- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
__block LAInAppHelperRequest *req = [[LAInAppHelperRequest alloc] initWithHelper:self andCompletionHandler:^(BOOL success, NSArray *products) {
completionHandler(success, products);
req = nil;
}];
}